<?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: Ravi Kishan</title>
    <description>The latest articles on DEV Community by Ravi Kishan (@ravikishan).</description>
    <link>https://dev.to/ravikishan</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%2F1011719%2F31bfaa0f-44f8-4cc2-84ba-9ebaaed4e4c3.png</url>
      <title>DEV Community: Ravi Kishan</title>
      <link>https://dev.to/ravikishan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ravikishan"/>
    <language>en</language>
    <item>
      <title>How RelaxCSS Works: Building a TailwindCSS-Like Utility Engine</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Tue, 24 Jun 2025 05:59:38 +0000</pubDate>
      <link>https://dev.to/ravikishan/how-relaxcss-works-building-a-tailwindcss-like-utility-engine-21j6</link>
      <guid>https://dev.to/ravikishan/how-relaxcss-works-building-a-tailwindcss-like-utility-engine-21j6</guid>
      <description>&lt;h1&gt;
  
  
  Overview and Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;RelaxCSS&lt;/strong&gt; is a lightweight, Tailwind-inspired utility-first CSS engine implemented as a PostCSS plugin and CLI tool. Like Tailwind, it provides a rich set of pre-defined utility classes (e.g. &lt;code&gt;p-4&lt;/code&gt;, &lt;code&gt;bg-blue-500&lt;/code&gt;, &lt;code&gt;hover:text-white&lt;/code&gt;) and a configuration-driven design system. RelaxCSS aims to be minimal and extensible: it supports custom &lt;em&gt;theme&lt;/em&gt; values (colors, spacing, etc.), responsive and pseudo-class variants, JIT compilation of only used utilities, and a plugin API for adding new utilities. Under the hood, a “preflight” (CSS reset) is injected (similar to Tailwind’s) and directives like &lt;code&gt;@apply&lt;/code&gt; and &lt;code&gt;@relax&lt;/code&gt; in CSS enable class composition.&lt;/p&gt;

&lt;p&gt;In practice, you install RelaxCSS, write your CSS/HTML with utility classes, and run the CLI (or PostCSS plugin) to watch your files. The tool &lt;strong&gt;scans source files for class names&lt;/strong&gt; (using glob patterns and regex), generates the corresponding utility CSS on-the-fly (JIT), and writes out a final &lt;code&gt;output.css&lt;/code&gt;. The default configuration (which you can customize via &lt;code&gt;relaxcss.config.js&lt;/code&gt;) includes sensible defaults for colors, spacing, screens, etc., and even a built-in example plugin (adding a &lt;code&gt;fancy-border&lt;/code&gt; utility). Overall, RelaxCSS provides a Tailwind-like workflow—class-heavy markup and zero custom CSS—while remaining small and easy to extend.&lt;/p&gt;

&lt;h1&gt;
  
  
  Architecture Overview
&lt;/h1&gt;

&lt;p&gt;RelaxCSS consists of several major components that work together in a build pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CLI/Watcher:&lt;/strong&gt; A command-line interface (&lt;code&gt;cli.ts&lt;/code&gt;/&lt;code&gt;cli-watch.ts&lt;/code&gt;) runs RelaxCSS. It uses &lt;a href="https://npmjs.com/package/glob" rel="noopener noreferrer"&gt;glob&lt;/a&gt; and &lt;a href="https://npmjs.com/package/chokidar" rel="noopener noreferrer"&gt;chokidar&lt;/a&gt; to watch source files (HTML, CSS, JS, etc.) and trigger rebuilds on changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Scanner (JIT Engine):&lt;/strong&gt; The CLI watches file patterns (e.g. &lt;code&gt;src/**/*.{html,js,jsx,ts,tsx,css}&lt;/code&gt;), reads each file’s content, and extracts class names with regex.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PostCSS Parser:&lt;/strong&gt; RelaxCSS is implemented as a &lt;a href="https://postcss.org/" rel="noopener noreferrer"&gt;PostCSS&lt;/a&gt; plugin. The plugin receives the CSS AST parsed from your combined stylesheet (including your &lt;code&gt;@apply&lt;/code&gt; rules).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Theme/Config:&lt;/strong&gt; User configuration (from &lt;code&gt;relaxcss.config.js&lt;/code&gt; or plugin options) is merged with the default theme/variants. This config object (colors, spacing, screens, etc.) is provided to the plugin and to any utility-generating code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Utility Generator (Plugin Logic):&lt;/strong&gt; The core plugin takes each utility class name (or &lt;code&gt;@apply&lt;/code&gt; directive) and generates the corresponding CSS declarations based on the theme config. It supports responsive prefixes (e.g. &lt;code&gt;md:&lt;/code&gt;), pseudo-classes (e.g. &lt;code&gt;hover:&lt;/code&gt;), and even arbitrary values (&lt;code&gt;bg-[#222]&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Output Generator:&lt;/strong&gt; After PostCSS transforms (including preflight injection and &lt;code&gt;@apply&lt;/code&gt; resolution), the plugin emits the final CSS. The CLI then writes this CSS to the output file (e.g. &lt;code&gt;dist/output.css&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fj5jmgbhxbllrc52rivu6.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%2Fj5jmgbhxbllrc52rivu6.png" alt="RelaxCSS Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this flow, the &lt;strong&gt;CLI&lt;/strong&gt; initiates file scanning (with glob and chokidar) and combines CSS and &lt;code&gt;@apply&lt;/code&gt; rules. The &lt;strong&gt;PostCSS parser&lt;/strong&gt; parses the CSS, and the &lt;strong&gt;RelaxCSS plugin&lt;/strong&gt; transforms it: injecting base styles (preflight), resolving &lt;code&gt;@apply&lt;/code&gt; by inlining utility declarations, and wrapping rules in media/pseudo selectors. The &lt;strong&gt;theme/config&lt;/strong&gt; drives which CSS values get used. Finally, the &lt;strong&gt;Output Generator&lt;/strong&gt; writes out the CSS file.&lt;/p&gt;

&lt;h1&gt;
  
  
  Theme and Configuration System
&lt;/h1&gt;

&lt;p&gt;RelaxCSS is highly configurable via a &lt;code&gt;relaxcss.config.js&lt;/code&gt; (or via plugin options). The user config can define custom &lt;strong&gt;theme values&lt;/strong&gt; (colors, spacing, fonts, etc.), &lt;strong&gt;responsive breakpoints&lt;/strong&gt;, &lt;strong&gt;variants&lt;/strong&gt; (e.g. which pseudo-classes to enable), &lt;strong&gt;plugins&lt;/strong&gt;, and more. Internally, RelaxCSS starts with a &lt;code&gt;defaultConfig&lt;/code&gt; (built-in) and merges the user’s config into it using &lt;a href="https://lodash.com/docs/#merge" rel="noopener noreferrer"&gt;lodash.merge&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mergedConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;defaultConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This merged config object, &lt;code&gt;mergedConfig&lt;/code&gt;, contains all theme scales. For example, the default theme includes a &lt;code&gt;screens&lt;/code&gt; section (for breakpoints) and a &lt;code&gt;spacing&lt;/code&gt; section:&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="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;640px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;768px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1024px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;xl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1280px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;px&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.25rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.5rem&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transparent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#eff6ff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#dbeafe&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.5rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt; &lt;span class="nx"&gt;xl&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.25rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,{&lt;/span&gt;&lt;span class="na"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.75rem&lt;/span&gt;&lt;span class="dl"&gt;"&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="c1"&gt;// etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Within the plugin code, CSS generation functions access these theme values. For example, when handling &lt;code&gt;max-w-&amp;lt;key&amp;gt;&lt;/code&gt; utilities, the code does:&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;max-w-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;suffix&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;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;max-width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Similarly, for font sizes (&lt;code&gt;text-xl&lt;/code&gt;), it retrieves a tuple from &lt;code&gt;config.theme.fontSize&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fontSizeTuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;suffix&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fontSizeTuple&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-size&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fontSizeTuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="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;fontSizeTuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;lineHeight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;declarations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line-height&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fontSizeTuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;lineHeight&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In summary, RelaxCSS loads user settings (via &lt;code&gt;opts&lt;/code&gt; or a &lt;code&gt;relaxcss.config.js&lt;/code&gt;), merges them with defaults, and then all parts of the system read from this &lt;code&gt;mergedConfig.theme&lt;/code&gt;. The &lt;code&gt;variants&lt;/code&gt; section (e.g. which media queries and which pseudo-classes to support) also comes from the config and drives how the plugin wraps utility rules for &lt;code&gt;sm:&lt;/code&gt; or &lt;code&gt;hover:&lt;/code&gt; prefixes.&lt;/p&gt;
&lt;h1&gt;
  
  
  Utility Parser and Generator
&lt;/h1&gt;

&lt;p&gt;At the heart of RelaxCSS is the &lt;em&gt;utility parser&lt;/em&gt;, which takes a class name like &lt;code&gt;p-4&lt;/code&gt;, &lt;code&gt;bg-[#222]&lt;/code&gt;, or &lt;code&gt;md:hover:bg-blue-500&lt;/code&gt; and translates it into one or more CSS declarations. This logic lives in the function &lt;code&gt;generateUtilityCss(className, config)&lt;/code&gt; in &lt;code&gt;index.ts&lt;/code&gt;. The class name is split into a &lt;strong&gt;prefix&lt;/strong&gt; (e.g. &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;bg&lt;/code&gt;, &lt;code&gt;text&lt;/code&gt;, etc.) and a &lt;strong&gt;suffix&lt;/strong&gt; (the part after the dash). A series of &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt; and &lt;code&gt;switch&lt;/code&gt; statements handle each utility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Spacing utilities&lt;/strong&gt; (&lt;code&gt;p-4&lt;/code&gt;, &lt;code&gt;mt-2&lt;/code&gt;, &lt;code&gt;mx-auto&lt;/code&gt;, etc.): use helper functions that look up the numeric key in &lt;code&gt;config.theme.spacing&lt;/code&gt; and emit corresponding &lt;code&gt;padding&lt;/code&gt; or &lt;code&gt;margin&lt;/code&gt; declarations. For example, &lt;code&gt;m-4&lt;/code&gt; becomes &lt;code&gt;margin: 1rem&lt;/code&gt; if &lt;code&gt;spacing[4] = "1rem"&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Size limits&lt;/strong&gt; (&lt;code&gt;max-w-lg&lt;/code&gt;, &lt;code&gt;max-h-full&lt;/code&gt;): look up in &lt;code&gt;config.theme.maxWidth&lt;/code&gt; or &lt;code&gt;maxHeight&lt;/code&gt; (from the merged config) and emit &lt;code&gt;max-width&lt;/code&gt; or &lt;code&gt;max-height&lt;/code&gt;. See above in .&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Colors and fonts&lt;/strong&gt;: for &lt;code&gt;text-&amp;lt;color&amp;gt;-&amp;lt;shade&amp;gt;&lt;/code&gt; or &lt;code&gt;bg-&amp;lt;color&amp;gt;-&amp;lt;shade&amp;gt;&lt;/code&gt;, a helper (&lt;code&gt;getColor&lt;/code&gt;) checks the nested &lt;code&gt;config.theme.colors&lt;/code&gt;. For &lt;code&gt;text-xl&lt;/code&gt;, it instead looks in &lt;code&gt;config.theme.fontSize&lt;/code&gt; as shown in .&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Importantly, RelaxCSS also supports &lt;strong&gt;arbitrary values&lt;/strong&gt; via a special parser function. A class like &lt;code&gt;bg-[#222]&lt;/code&gt; or &lt;code&gt;p-[4px]&lt;/code&gt; matches the regex &lt;code&gt;/^([a-z-]+)-\[(.+)\]$/&lt;/code&gt;. This extracts a &lt;code&gt;prefix&lt;/code&gt; and a raw &lt;code&gt;value&lt;/code&gt;. The code &lt;code&gt;parseArbitraryValue(className, config)&lt;/code&gt; (see below) directly maps certain prefixes to CSS properties:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parseArbitraryValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;className&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RelaxConfig&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// e.g. bg-[#222], p-[4px], text-[red], w-[100px], m-[1rem], etc.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arbitraryMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;([&lt;/span&gt;&lt;span class="sr"&gt;a-z-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;\[(&lt;/span&gt;&lt;span class="sr"&gt;.+&lt;/span&gt;&lt;span class="se"&gt;)\]&lt;/span&gt;&lt;span class="sr"&gt;$/i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;arbitraryMatch&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arbitraryMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arbitraryMatch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="c1"&gt;// Map prefix to CSS property&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background-color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})];&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})];&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border-color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})];&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;w&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})];&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})];&lt;/span&gt;
    &lt;span class="c1"&gt;// ... handle px, py, m, etc. in a similar way ...&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;// fallback: treat prefix as the property name&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;})];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When the PostCSS plugin encounters a utility class, it first tries &lt;code&gt;parseArbitraryValue&lt;/code&gt;. If that returns declarations, it uses them directly (for example, &lt;code&gt;bg-[#222]&lt;/code&gt; yields &lt;code&gt;background-color: #222&lt;/code&gt;). Otherwise, it falls back to the standard &lt;code&gt;generateUtilityCss&lt;/code&gt; logic for named utilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Responsive and pseudo variants:&lt;/strong&gt; Class names can be prefixed with media queries or pseudo-classes, like &lt;code&gt;sm:&lt;/code&gt;, &lt;code&gt;md:&lt;/code&gt;, &lt;code&gt;hover:&lt;/code&gt;, &lt;code&gt;focus:&lt;/code&gt;, etc. In RelaxCSS this is handled in the plugin as well. The CLI/JIT will detect a class like &lt;code&gt;md:hover:bg-blue-500&lt;/code&gt; and enqueue it. The plugin code splits on &lt;code&gt;":"&lt;/code&gt; to see that &lt;code&gt;md&lt;/code&gt; is a responsive variant and &lt;code&gt;hover&lt;/code&gt; is a pseudo-variant, and then wraps the generated declarations accordingly. For example, &lt;code&gt;md:hover:bg-blue-500&lt;/code&gt; results in a rule inside a &lt;code&gt;@media (min-width: 768px)&lt;/code&gt; block, with selector &lt;code&gt;.md\:hover\:bg-blue-500:hover { background-color: ... }&lt;/code&gt;. (The plugin has helper code to do this, but the key point is that our design allows stacking variants in class names.)&lt;/p&gt;

&lt;p&gt;For standard utilities (without variants), the code essentially turns a class into a CSS rule of the form &lt;code&gt;.&amp;lt;class&amp;gt; { &amp;lt;declarations&amp;gt; }&lt;/code&gt;. For example, &lt;code&gt;text-xl&lt;/code&gt; would lead to:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.text-xl {
  font-size: 1.25rem; /* from theme */
  line-height: 1.75rem; /* from theme */
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Likewise, &lt;code&gt;.bg-blue-500 { background-color: #3b82f6; }&lt;/code&gt;. Arbitrary values work similarly: &lt;code&gt;.bg-\[\#222\] { background-color: #222; }&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Plugin System
&lt;/h1&gt;

&lt;p&gt;RelaxCSS provides a &lt;strong&gt;plugin API&lt;/strong&gt; so users can register additional utilities. A plugin is simply a function receiving an API object, e.g.:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;RelaxPlugin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;addUtilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RelaxConfig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Declaration&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RelaxConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="k"&gt;void&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;Within this function, a plugin typically calls &lt;code&gt;api.addUtilities(...)&lt;/code&gt; with new utility definitions. For example, the default config includes a built-in plugin that adds a &lt;code&gt;fancy-border&lt;/code&gt; utility:&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="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;addUtilities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;addUtilities&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fancy-border&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// This utility generates: border:2px dashed magenta;&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Declaration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;border&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2px dashed magenta&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After loading the config, RelaxCSS iterates through any &lt;code&gt;plugins&lt;/code&gt; array (if provided) and calls each plugin function. The &lt;code&gt;addUtilities&lt;/code&gt; calls aggregate into a &lt;code&gt;userUtilities&lt;/code&gt; map. Later, during CSS generation, these custom utilities are treated just like built-in ones: if a class matches &lt;code&gt;"fancy-border"&lt;/code&gt;, RelaxCSS will output the declarations given by that plugin function.&lt;/p&gt;

&lt;p&gt;This plugin mechanism allows anyone to extend RelaxCSS with their own custom shortcut classes (e.g. new color utilities, or even complex components) without modifying the core engine.&lt;/p&gt;
&lt;h1&gt;
  
  
  JIT Compilation and File Scanning
&lt;/h1&gt;

&lt;p&gt;The CLI tool (&lt;code&gt;cli-watch.ts&lt;/code&gt;) implements a &lt;strong&gt;Just-In-Time (JIT) engine&lt;/strong&gt;. Instead of generating &lt;em&gt;all possible&lt;/em&gt; utility classes, it scans your source files on-the-fly for exactly the classes you use. Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File watching:&lt;/strong&gt; The CLI takes a glob pattern like &lt;code&gt;src/**/*.html&lt;/code&gt; and uses &lt;code&gt;glob.sync&lt;/code&gt; to find matching files. It then sets up a watcher with &lt;code&gt;chokidar.watch(srcGlob)&lt;/code&gt; to re-run the scan whenever any matching file changes. This makes it incremental and efficient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Class extraction:&lt;/strong&gt; For each source file, the code reads its contents and uses a regex to find class names. For HTML/JSX/etc, it matches &lt;code&gt;class="..."&lt;/code&gt;, &lt;code&gt;className="..."&lt;/code&gt;, or Vue &lt;code&gt;:class="..."&lt;/code&gt;, etc. The regex used is:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;classRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?:&lt;/span&gt;&lt;span class="sr"&gt;class|className|:class&lt;/span&gt;&lt;span class="se"&gt;)\s&lt;/span&gt;&lt;span class="sr"&gt;*=&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;"'`&lt;/span&gt;&lt;span class="se"&gt;\{&lt;/span&gt;&lt;span class="sr"&gt;[&lt;/span&gt;&lt;span class="se"&gt;]([^&lt;/span&gt;&lt;span class="sr"&gt;"'`&lt;/span&gt;&lt;span class="se"&gt;\}\]]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)[&lt;/span&gt;&lt;span class="sr"&gt;"'`&lt;/span&gt;&lt;span class="se"&gt;\}]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Then it splits the captured class string on whitespace. For example, in &lt;code&gt;&amp;lt;div class="text-xl p-4 hover:bg-red-500"&amp;gt;&lt;/code&gt;, it will extract &lt;code&gt;["text-xl","p-4","hover:bg-red-500"]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;CSS files are also scanned for &lt;code&gt;@apply&lt;/code&gt; directives: another regex &lt;code&gt;/@apply\s+([^;]+);/g&lt;/code&gt; pulls out any classes listed in an &lt;code&gt;@apply&lt;/code&gt; statement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Building CSS to apply:&lt;/strong&gt; After scanning all files, the CLI builds a temporary CSS string where each found class is “applied” via &lt;code&gt;@apply&lt;/code&gt;. For example, if it found &lt;code&gt;text-lg&lt;/code&gt; and &lt;code&gt;mt-4&lt;/code&gt;, it generates:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.text-lg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;text-lg;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.mt-4&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;mt-4;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;(It also handles variants by calling a helper &lt;code&gt;generateTailwindVariantRule&lt;/code&gt;, but ultimately it creates &lt;code&gt;@apply&lt;/code&gt; rules for each used class.) This combined CSS (plus any raw CSS content) is then fed into PostCSS with the RelaxCSS plugin.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic rebuilds:&lt;/strong&gt; Thanks to &lt;code&gt;chokidar&lt;/code&gt;, any file change triggers the scan-and-build process again. This ensures the output CSS is always up-to-date with the classes in your source.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Key code excerpts from &lt;code&gt;cli-watch.ts&lt;/code&gt;:&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;// Scan files for classes and @apply&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;srcGlob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[RelaxCSS] Processing files matching: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extname&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="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;css&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="nx"&gt;combinedCss&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;extractApplyClasses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cls&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;foundClasses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileExtensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ext&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;extractClassNames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cls&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;foundClasses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;classNameFoundClasses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;extractClassNames&lt;/code&gt; and &lt;code&gt;extractApplyClasses&lt;/code&gt; functions use regexes to find classes:&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;// In cli-watch.ts:&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;extractClassNames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="c1"&gt;// Match class="...", className="...", etc.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;classRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?:&lt;/span&gt;&lt;span class="sr"&gt;class|className|:class&lt;/span&gt;&lt;span class="se"&gt;)\s&lt;/span&gt;&lt;span class="sr"&gt;*=&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;"'`&lt;/span&gt;&lt;span class="se"&gt;\{&lt;/span&gt;&lt;span class="sr"&gt;[&lt;/span&gt;&lt;span class="se"&gt;]([^&lt;/span&gt;&lt;span class="sr"&gt;"'`&lt;/span&gt;&lt;span class="se"&gt;\}\]]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)[&lt;/span&gt;&lt;span class="sr"&gt;"'`&lt;/span&gt;&lt;span class="se"&gt;\}]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;classRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cls&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// ignore Spread syntax&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After extracting, the watcher rebuild logic looks like:&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;// Watch for changes and rebuild&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chokidar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;srcGlob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ignoreInitial&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="nx"&gt;watcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&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="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[RelaxCSS] Detected &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; in &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Rebuilding...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;processFiles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This JIT pipeline – &lt;em&gt;scan source → extract classes → generate &lt;a class="mentioned-user" href="https://dev.to/apply"&gt;@apply&lt;/a&gt; CSS → run RelaxCSS plugin&lt;/em&gt; – ensures that only used utilities end up in the final CSS. We can diagram it as:&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%2Fqapaw6z38ssifr1f78ag.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%2Fqapaw6z38ssifr1f78ag.png" alt="RelaxCSS JIT Compilation Pipeline"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Preflight and CSS Output
&lt;/h1&gt;

&lt;p&gt;By default, RelaxCSS injects a small &lt;strong&gt;preflight&lt;/strong&gt; (base reset) at the top of the CSS. This is similar to Tailwind’s Preflight and is meant to normalize browser defaults. In the plugin code, you can see it defines sections like “box-sizing”, “margin-padding”, “list-style”, etc.:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;preflightSections&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;box-sizing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`*,*::before,*::after{box-sizing:border-box;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;margin-padding&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`body,h1,h2,h3,h4,h5,h6,p,ul,ol,li,figure,figcaption,blockquote,dl,dd{margin:0;padding:0;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;list-style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`ul:not([class]),ol:not([class]){list-style:none;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;font-family&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`body{font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Open Sans","Helvetica Neue",sans-serif;line-height:1.5;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;media&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`img,picture,video,canvas,svg{display:block;max-width:100%;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;table&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`table{border-collapse:collapse;}th,td{padding:0;}`&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;These CSS snippets (with comments like &lt;code&gt;/* RelaxCSS Preflight: box-sizing */&lt;/code&gt;) are prepended to the output. The &lt;code&gt;preflight&lt;/code&gt; section of the config allows enabling/disabling parts or adding overrides, but by default all sections are included. For example, the first injected rule is &lt;code&gt;*,*::before,*::after{box-sizing:border-box;}&lt;/code&gt; (ensuring consistent box-sizing).&lt;/p&gt;

&lt;p&gt;After the plugin runs (resolving all &lt;code&gt;@apply&lt;/code&gt; rules into concrete declarations and wrapping variants), the final CSS is emitted. In &lt;code&gt;cli-watch.ts&lt;/code&gt;, this is done with PostCSS:&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="nf"&gt;postcss&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="nf"&gt;relaxcss&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;finalCss&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outFile&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&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="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[RelaxCSS] Rebuilt: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;outFile&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[RelaxCSS] Build error:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So the &lt;strong&gt;final output&lt;/strong&gt; is a single CSS file that begins with the preflight rules, followed by your combined utilities. All &lt;code&gt;@apply&lt;/code&gt; rules have been replaced by their actual CSS declarations. For instance, if you had:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@relax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;flex&lt;/span&gt; &lt;span class="err"&gt;bg-[#222]&lt;/span&gt; &lt;span class="py"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bg-&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;#333&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 output might look like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* RelaxCSS Preflight: box-sizing */&lt;/span&gt;
&lt;span class="o"&gt;*,*&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,*&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="c"&gt;/* RelaxCSS Preflight: margin-padding */&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,...,&lt;/span&gt;&lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="c"&gt;/* ... other preflight rules ... */&lt;/span&gt;

&lt;span class="c"&gt;/* Utility classes */&lt;/span&gt;
&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#222&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.md&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:bg-&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\#333\&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the example above, &lt;code&gt;.container&lt;/code&gt; got &lt;code&gt;display:flex&lt;/code&gt; (from the &lt;code&gt;flex&lt;/code&gt; utility) and &lt;code&gt;background-color:#222&lt;/code&gt; (from &lt;code&gt;bg-[#222]&lt;/code&gt;). The &lt;code&gt;md:hover:bg-[#333]&lt;/code&gt; utility generated a media query rule for screens &lt;code&gt;&amp;gt;=768px&lt;/code&gt; with the selector &lt;code&gt;.md:hover:bg-[#333]:hover&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Example Output and Live Usage
&lt;/h1&gt;

&lt;p&gt;Suppose we have an input CSS file like &lt;code&gt;src/input.css&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* src/input.css */&lt;/span&gt;
&lt;span class="k"&gt;@relax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;flex&lt;/span&gt; &lt;span class="err"&gt;bg-[#222]&lt;/span&gt; &lt;span class="py"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bg-&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.my-box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;fancy-border;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.ravi&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;text-2xl;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.kishan&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;text-3xl;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here we use &lt;code&gt;@relax;&lt;/code&gt; to trigger the plugin, and we apply several utilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;flex&lt;/code&gt;, &lt;code&gt;bg-[#222]&lt;/code&gt;, and &lt;code&gt;md:hover:bg-[#333]&lt;/code&gt; on &lt;code&gt;.container&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fancy-border&lt;/code&gt; on &lt;code&gt;.my-box&lt;/code&gt; (this was a custom utility from the default plugin).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;text-2xl&lt;/code&gt; and &lt;code&gt;text-3xl&lt;/code&gt; on &lt;code&gt;.ravi&lt;/code&gt; and &lt;code&gt;.kishan&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running RelaxCSS on this (&lt;code&gt;npx ts-node src/cli-watch.ts "src/**/*.{css,html,js,jsx,ts,tsx}" --out dist/output.css&lt;/code&gt;) will produce a &lt;code&gt;dist/output.css&lt;/code&gt; roughly like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* RelaxCSS Preflight: box-sizing */&lt;/span&gt;
&lt;span class="o"&gt;*,*&lt;/span&gt;&lt;span class="nd"&gt;::before&lt;/span&gt;&lt;span class="o"&gt;,*&lt;/span&gt;&lt;span class="nd"&gt;::after&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="c"&gt;/* RelaxCSS Preflight: margin-padding */&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;h6&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;figcaption&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;blockquote&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;dl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
&lt;span class="c"&gt;/* ... other preflight rules ... */&lt;/span&gt;

&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#222&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.md&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nd"&gt;:bg-&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\#333\&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&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="nc"&gt;.my-box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;dashed&lt;/span&gt; &lt;span class="no"&gt;magenta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.ravi&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.kishan&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.875rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2.25rem&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;For live usage, one might have an HTML file like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"m-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hover:bg-blue-500 hover:text-white md:hover:bg-blue-700 bg-[#222]"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Hover over me
  &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When RelaxCSS processes this (in JIT mode), it will generate the equivalent CSS so that the button responds to hover and changes background/text color as expected.&lt;/p&gt;
&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;RelaxCSS is a compact, flexible framework for utility-first styling, suitable for frontend developers and framework authors who want Tailwind-like productivity with a smaller footprint. It leverages a &lt;strong&gt;PostCSS plugin&lt;/strong&gt; to parse utility class names (&lt;code&gt;p-4&lt;/code&gt;, &lt;code&gt;text-blue-500&lt;/code&gt;, &lt;code&gt;hover:bg-red-200&lt;/code&gt;, etc.) and emit the corresponding CSS using values from a &lt;strong&gt;theme configuration&lt;/strong&gt;. The &lt;strong&gt;CLI/JIT&lt;/strong&gt; engine watches your files and includes only the utilities you actually use, keeping the CSS minimal. The &lt;strong&gt;plugin system&lt;/strong&gt; lets you define your own utilities or copy Tailwind’s plugin approach. By supporting arbitrary values (&lt;code&gt;bg-[#222]&lt;/code&gt;), responsive prefixes (&lt;code&gt;md:&lt;/code&gt;) and variants (&lt;code&gt;hover:&lt;/code&gt;), plus a built-in preflight reset, RelaxCSS covers most needs of modern utility-based development.&lt;/p&gt;

&lt;p&gt;For advanced use, you can extend RelaxCSS by adding more functions to &lt;code&gt;generateUtilityCss&lt;/code&gt;, writing plugins with &lt;code&gt;addUtilities&lt;/code&gt;, or customizing the configuration. Because it’s just a PostCSS plugin and Node script, you could even integrate it into larger build tools or frameworks. Overall, RelaxCSS aims to be a learning-friendly, extensible alternative to Tailwind for projects where you want control over the utility engine’s internals. Users can build on this foundation – for example, adding support for more CSS features or improving performance – thanks to its clear architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt; The above explanations and code snippets are drawn directly from the RelaxCSS source files (e.g. &lt;code&gt;index.ts&lt;/code&gt;, &lt;code&gt;cli-watch.ts&lt;/code&gt;, &lt;code&gt;base.css&lt;/code&gt;).&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Ravikisha" rel="noopener noreferrer"&gt;
        Ravikisha
      &lt;/a&gt; / &lt;a href="https://github.com/Ravikisha/RelaxCSS" rel="noopener noreferrer"&gt;
        RelaxCSS
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A next-generation, Tailwind-like JIT CSS/PostCSS plugin with a powerful plugin system, support for arbitrary values, variants (including dark mode and RTL), efficient watch mode, and CSS variable theme support.  RelaxCSS can be used as a PostCSS plugin (recommended for most build pipelines) or as a standalone CLI tool.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/25b192c6b99c5cc9ee753bf44a208bea66ffabc7dbb0e43169dbaeae89cefcf1/68747470733a2f2f726176696b697368612e6769746875622e696f2f6173736574732f72656c61786373735f6c6f676f2e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/25b192c6b99c5cc9ee753bf44a208bea66ffabc7dbb0e43169dbaeae89cefcf1/68747470733a2f2f726176696b697368612e6769746875622e696f2f6173736574732f72656c61786373735f6c6f676f2e706e67" alt="RelaxCSS Logo" width="200"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;RelaxCSS&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/12648c2ce61ec5b0cd3ac890a4e58227b4383a99d2cfc699f0f0bbc3a1db2aca/68747470733a2f2f736869656c64732e696f2f62616467652f547970655363726970742d3331373843363f6c6f676f3d54797065536372697074266c6f676f436f6c6f723d464646267374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/12648c2ce61ec5b0cd3ac890a4e58227b4383a99d2cfc699f0f0bbc3a1db2aca/68747470733a2f2f736869656c64732e696f2f62616467652f547970655363726970742d3331373843363f6c6f676f3d54797065536372697074266c6f676f436f6c6f723d464646267374796c653d666c61742d737175617265" alt="Typescript Logo"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/08c91bdd8420a2513ed7d16fd83a8b5253054e5e94c9c277d00bf28a1559d8d0/68747470733a2f2f736869656c64732e696f2f62616467652f4a6176615363726970742d4637444631453f6c6f676f3d4a617661536372697074266c6f676f436f6c6f723d303030267374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/08c91bdd8420a2513ed7d16fd83a8b5253054e5e94c9c277d00bf28a1559d8d0/68747470733a2f2f736869656c64732e696f2f62616467652f4a6176615363726970742d4637444631453f6c6f676f3d4a617661536372697074266c6f676f436f6c6f723d303030267374796c653d666c61742d737175617265" alt="JavaScript Logo"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/1504d358626062a15d1b2cd5da02d3497c67502055f18e9a13e48f46769fd688/68747470733a2f2f736869656c64732e696f2f62616467652f506f73744353532d3030303030303f6c6f676f3d506f7374435353266c6f676f436f6c6f723d464646267374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/1504d358626062a15d1b2cd5da02d3497c67502055f18e9a13e48f46769fd688/68747470733a2f2f736869656c64732e696f2f62616467652f506f73744353532d3030303030303f6c6f676f3d506f7374435353266c6f676f436f6c6f723d464646267374796c653d666c61742d737175617265" alt="PostCSS Logo"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/6b1af2dc96fa8b32f9bdc35d0f15085e6ff534810d868167c4636238015aba8c/68747470733a2f2f736869656c64732e696f2f62616467652f4e6f64652e6a732d3333393933333f6c6f676f3d4e6f64652e6a73266c6f676f436f6c6f723d464646267374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/6b1af2dc96fa8b32f9bdc35d0f15085e6ff534810d868167c4636238015aba8c/68747470733a2f2f736869656c64732e696f2f62616467652f4e6f64652e6a732d3333393933333f6c6f676f3d4e6f64652e6a73266c6f676f436f6c6f723d464646267374796c653d666c61742d737175617265" alt="Node.js Logo"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/5cfde9ac032dd6b75594ba4cddca5cd484de755ed112485d2e460895cbf747ad/68747470733a2f2f736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d626c75653f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/5cfde9ac032dd6b75594ba4cddca5cd484de755ed112485d2e460895cbf747ad/68747470733a2f2f736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d626c75653f7374796c653d666c61742d737175617265" alt="MIT License"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;A next-generation, Tailwind-like JIT CSS/PostCSS plugin with a powerful plugin system, support for arbitrary values, variants (including dark mode and RTL), efficient watch mode, and CSS variable theme support.&lt;/p&gt;

&lt;p&gt;RelaxCSS can be used as a &lt;strong&gt;PostCSS plugin&lt;/strong&gt; (recommended for most build pipelines) or as a standalone CLI tool.&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;PostCSS Plugin Usage&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;RelaxCSS is a drop-in &lt;a href="https://postcss.org/" rel="nofollow noopener noreferrer"&gt;PostCSS&lt;/a&gt; plugin. It works with PostCSS v8+ and integrates with any PostCSS-based build system (Webpack, Vite, Parcel, etc).&lt;/p&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// postcss.config.js&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;relaxcss&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'relaxcss'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-smi"&gt;module&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;exports&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;plugins&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;
    &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'postcss-import'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-c"&gt;// must be first&lt;/span&gt;
    &lt;span class="pl-s1"&gt;relaxcss&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;
      &lt;span class="pl-c"&gt;// custom config here&lt;/span&gt;
    &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'autoprefixer'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
    &lt;span class="pl-c"&gt;// ...&lt;/span&gt;
  &lt;span class="pl-kos"&gt;]&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Supports all RelaxCSS features: JIT utilities, plugins, variants, dark mode, RTL, CSS variables, and more.&lt;/li&gt;
&lt;li&gt;Use your &lt;code&gt;relaxcss.config.js&lt;/code&gt; for custom configuration.&lt;/li&gt;
&lt;li&gt;Compatible with PostCSS v8+ and all major build…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Ravikisha/RelaxCSS" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://www.npmjs.com/package/relaxcss" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;npmjs.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Building a Container Runtime from Scratch with Go (MyDocker)</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Thu, 05 Jun 2025 13:25:34 +0000</pubDate>
      <link>https://dev.to/ravikishan/building-a-container-runtime-from-scratch-with-go-mydocker-o7p</link>
      <guid>https://dev.to/ravikishan/building-a-container-runtime-from-scratch-with-go-mydocker-o7p</guid>
      <description>&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Introduction: What is a Container Runtime?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Namespaces: Isolating Processes on Linux&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Control Groups (cgroups): Managing Resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Project Architecture: The MyDocker Design&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Command-Line Interface and Main.go&lt;/li&gt;
&lt;li&gt;Container Lifecycle (&lt;code&gt;startContainer&lt;/code&gt;, &lt;code&gt;child&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Networking Isolation (Bridge and veth)&lt;/li&gt;
&lt;li&gt;Image Handling and OCI Unpacking&lt;/li&gt;
&lt;li&gt;Volumes and Port Mappings&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Diagrams: Visualizing the Runtime&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Getting Started and Resources&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;Containers are lightweight, isolated environments for running applications. Unlike virtual machines, containers share the host kernel but &lt;strong&gt;isolate&lt;/strong&gt; processes using kernel features like namespaces and cgroups. In this tutorial we’ll explore &lt;em&gt;MyDocker&lt;/em&gt;, a simple container runtime written in Go, and walk through the key pieces that make it work. We’ll explain how MyDocker uses Linux namespaces (UTS, PID, network, mount, etc.) to isolate the container’s view of the system, and how it uses cgroups to limit resources. Along the way we’ll show key code snippets (e.g. &lt;code&gt;startContainer&lt;/code&gt;, &lt;code&gt;child&lt;/code&gt;, &lt;code&gt;execContainer&lt;/code&gt;) and outline MyDocker’s architecture for CLI commands, networking, and image handling. By the end, you’ll see how MyDocker’s internals fit together, and how OCI image unpacking with tools like &lt;em&gt;umoci&lt;/em&gt; and simple mount/iptables tricks provide the functionality of &lt;code&gt;docker pull&lt;/code&gt;, &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, and more. We encourage you to check out the [MyDocker GitHub repository][22] and its [README][26] for examples and to try extending the code yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Namespaces
&lt;/h2&gt;

&lt;p&gt;Linux &lt;strong&gt;namespaces&lt;/strong&gt; provide isolation by giving a process its own “view” of system resources. For example, PID namespaces mean a process can see only processes in its own container; UTS namespaces let each container have its own hostname; mount namespaces give each container its own filesystem root; network namespaces provide separate network interfaces/iptables, and so on. In other words, namespaces prevent processes in one container from seeing or affecting those in another. This isolation is a cornerstone of container security: “namespaces are quite flexible…they can be applied individually or in groups to one or more processes”. MyDocker’s container “child” process is created with clone flags for multiple namespaces (UTS, PID, NET, mount, etc.), so it runs in isolation. The code roughly follows the pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// In main or run command:&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/proc/self/exe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"child"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysProcAttr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysProcAttr&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Cloneflags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLONE_NEWUTS&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLONE_NEWPID&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLONE_NEWNET&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
                &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLONE_NEWNS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c"&gt;// etc.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;
&lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="c"&gt;// The child() function runs inside the new namespaces:&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// e.g., set hostname inside UTS namespace&lt;/span&gt;
    &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sethostname&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mydocker"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c"&gt;// Possibly mount proc, chroot, pivot_root, etc.&lt;/span&gt;
    &lt;span class="c"&gt;// Finally exec the requested command:&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;
    &lt;span class="n"&gt;must&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As in other “container-from-scratch” examples, this pattern uses &lt;code&gt;exec.Command("/proc/self/exe", "child", …)&lt;/code&gt; to re-invoke the same program in a new process (in new namespaces). From outside, the &lt;code&gt;run&lt;/code&gt; command spawns the namespaced child; inside the container, the &lt;code&gt;child&lt;/code&gt; function does setup (hostname, filesystem mounts, etc.) and then executes the user’s command. This effectively gives the container its own isolated environment &lt;strong&gt;separate&lt;/strong&gt; from the host.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure: Container runtime architecture. MyDocker creates a namespaced “child” process for each container, mounts a fresh root filesystem (unpacked from an OCI image), applies cgroup limits, and sets up networking (bridge &lt;code&gt;mydocker0&lt;/code&gt; and veth pair). The CLI (main.go) drives commands like &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;pull&lt;/code&gt;, etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In summary, namespaces ensure that processes in MyDocker containers see only their own CPU, memory, filesystems, networks, and process list. This is one of the fundamental layers of container isolation. (MyDocker’s README also highlights this as a core feature: “Container process isolation using Linux namespaces (UTS, PID, NET, MNT)”.)&lt;/p&gt;
&lt;h2&gt;
  
  
  Control Groups (cgroups)
&lt;/h2&gt;

&lt;p&gt;While namespaces isolate &lt;em&gt;what&lt;/em&gt; a process sees, cgroups control &lt;em&gt;how much&lt;/em&gt; of a resource a process can use. A &lt;strong&gt;control group&lt;/strong&gt; (cgroup) is a Linux kernel feature that limits, accounts for, and isolates resource usage (CPU, memory, I/O, etc.) of a group of processes. MyDocker uses cgroups so that each container process has its own CPU and memory limits (as defined by CLI flags). For example, it might create a new cgroup under &lt;code&gt;/sys/fs/cgroup/cpu/mydocker/&amp;lt;id&amp;gt;&lt;/code&gt; and write the PID of the container process into it, along with any limits (like &lt;code&gt;cpu.shares&lt;/code&gt; or &lt;code&gt;memory.limit_in_bytes&lt;/code&gt;). This means the container will only get a fraction of CPU or a fixed amount of memory, protecting the host and other containers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Cgroups are a kernel feature that allows you to partition and limit the system resources… that a group of processes can use. Think of them as virtual cages where you can corral your processes and set rules for their behavior”&lt;/em&gt;. (This quote describes cgroups in general; MyDocker uses them specifically for CPU and memory limits.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For instance, MyDocker might contain code like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Simplified: create a cpu cgroup for the container&lt;/span&gt;
&lt;span class="n"&gt;cgroupPath&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/sys/fs/cgroup/cpu/mydocker"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;containerID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MkdirAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cgroupPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0755&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// write the container's PID into the cgroup.procs file&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cgroupPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cgroup.procs"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pidStr&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;0644&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;// optionally set limits like cpu.shares or memory.limit_in_bytes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This ensures each container is “in its own cage”. The MyDocker README emphasizes resource control: “Resource control via cgroups (CPU &amp;amp; Memory)”. By combining cgroups with namespaces, the runtime isolates both the &lt;em&gt;view&lt;/em&gt; and &lt;em&gt;resources&lt;/em&gt; of each container process, similarly to how Docker does it behind the scenes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Project Architecture
&lt;/h2&gt;

&lt;p&gt;MyDocker’s source is structured simply (see [Architecture Overview][100]). At the top level we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;main.go&lt;/code&gt; – The CLI entry point: parses commands like &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;pull&lt;/code&gt;, etc. It calls functions like &lt;code&gt;startContainer()&lt;/code&gt; or &lt;code&gt;execContainer()&lt;/code&gt; accordingly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;cgroups/&lt;/code&gt; – Go package to set up cgroup directories and limits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;network/&lt;/code&gt; – Go package to create a bridge (&lt;code&gt;mydocker0&lt;/code&gt;) and virtual ethernet (veth) pairs for container networking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;helper.c&lt;/code&gt; – A small C program that is used to join existing namespaces (see below).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other files: e.g. configuration templates, documentation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architecture overview in the README summarizes this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Architecture Overview: &lt;code&gt;main.go&lt;/code&gt; — The CLI and container runtime entry point; &lt;code&gt;cgroups/&lt;/code&gt; — resource limits; &lt;code&gt;network/&lt;/code&gt; — bridge networks/veth; &lt;code&gt;/var/lib/mydocker/&lt;/code&gt; — stores metadata/images”&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So when you run something like &lt;code&gt;sudo ./mydocker run -v /data:/data -p 8080:80 ubuntu:22.04 sh&lt;/code&gt;, what happens? A brief walkthrough:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CLI (&lt;code&gt;main.go&lt;/code&gt;)&lt;/strong&gt;: The program parses the &lt;code&gt;run&lt;/code&gt; command and container options (image name, mounts, ports, etc.). It likely calls a function &lt;code&gt;startContainer(containerID, command, flags...)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;startContainer&lt;/strong&gt;: This function creates a unique container ID, sets up storage (image unpack, rootfs), sets up networking, then spawns a child process in new namespaces (using &lt;code&gt;exec.Command("/proc/self/exe", ...)&lt;/code&gt; as above). It also records container metadata (like PID, rootfs path) under &lt;code&gt;/var/lib/mydocker/&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Child process&lt;/strong&gt;: In the new namespaces, it does further initialization: e.g., performs &lt;code&gt;chroot&lt;/code&gt;/&lt;code&gt;pivot_root&lt;/code&gt; into the unpacked image root filesystem; mounts the host directory if &lt;code&gt;-v&lt;/code&gt; was given; configures networking (calls &lt;code&gt;net.SetupVeth()&lt;/code&gt; to move one end of a veth into this namespace); then finally execs the user’s command (e.g. &lt;code&gt;sh&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Networking&lt;/strong&gt;: The &lt;code&gt;network/&lt;/code&gt; code ensures there is a Linux bridge (e.g. &lt;code&gt;mydocker0&lt;/code&gt;) on the host. It creates a veth pair, moves one end into the child’s net namespace (as &lt;code&gt;eth0&lt;/code&gt;), and attaches the other end to the &lt;code&gt;mydocker0&lt;/code&gt; bridge, giving the container network access (with its own IP).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cgroups&lt;/strong&gt;: Concurrently, before or after spawning the child, MyDocker creates new cgroup entries under CPU/memory controllers and adds the child’s PID, enforcing resource limits on that container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Image Unpacking&lt;/strong&gt;: For pulling images, MyDocker uses &lt;a href="https://github.com/opencontainers/umoci" rel="noopener noreferrer"&gt;&lt;code&gt;umoci&lt;/code&gt;&lt;/a&gt;. The &lt;code&gt;pull&lt;/code&gt; command downloads an OCI image (like Ubuntu) and uses &lt;code&gt;umoci unpack&lt;/code&gt; to extract it into a directory under &lt;code&gt;/var/lib/mydocker&lt;/code&gt;. &lt;em&gt;Umoci&lt;/em&gt; documentation explains: &lt;em&gt;“umoci unpack - Unpacks an OCI image tag into a runtime bundle”&lt;/em&gt;. In other words, MyDocker relies on umoci to convert a container image into a rootfs directory with config, just like Docker does with layered filesystems.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fkpony5dgbndp3im94v0p.jpg" 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%2Fkpony5dgbndp3im94v0p.jpg" alt="MyDocker Architecture"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Command-Line Interface and Main.go
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;main.go&lt;/code&gt; file defines the CLI commands (&lt;code&gt;run&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;ps&lt;/code&gt;, etc.) using a library like &lt;a href="https://github.com/urfave/cli" rel="noopener noreferrer"&gt;urfave/cli&lt;/a&gt;. For example, when the user runs &lt;code&gt;mydocker run ...&lt;/code&gt;, it ends up invoking something like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;runCommandAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cli&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;imageName&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GlobalFlags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;containerID&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;generateID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;startContainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;containerID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imageName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The core functions include &lt;strong&gt;&lt;code&gt;startContainer&lt;/code&gt;&lt;/strong&gt; (for &lt;code&gt;run&lt;/code&gt;) and &lt;strong&gt;&lt;code&gt;ExecContainer&lt;/code&gt;&lt;/strong&gt; (for &lt;code&gt;exec&lt;/code&gt;). In MyDocker, &lt;code&gt;startContainer&lt;/code&gt; will unpack the image if needed, set up cgroups/networks, then clone a new process.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;execContainer&lt;/code&gt;&lt;/strong&gt; function (called by &lt;code&gt;mydocker exec&lt;/code&gt;) is also interesting. It finds the PID of an existing container process (by reading stored metadata) and then uses &lt;code&gt;exec.Command("/proc/self/exe", "exec")&lt;/code&gt; to fork a helper process that enters that container’s namespaces (via a small C helper). Part of the code might look like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ExecContainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;containerID&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;comArray&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;getPidByContainerId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;containerID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c"&gt;// Set environment variables for the helper C program:&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/proc/self/exe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"exec"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Setenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mydocker_pid"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Setenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mydocker_cmd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;
    &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This tells the re-invoked process to run the &lt;code&gt;"exec"&lt;/code&gt; branch of &lt;code&gt;main()&lt;/code&gt;. The helper C code (in &lt;code&gt;helper.c&lt;/code&gt;) sees &lt;code&gt;mydocker_pid&lt;/code&gt;/&lt;code&gt;mydocker_cmd&lt;/code&gt; and performs &lt;code&gt;setns()&lt;/code&gt; calls to join the PID/UTS/NET namespaces of that container, then uses &lt;code&gt;system(mydocker_cmd)&lt;/code&gt; to run the desired command inside the container. (In effect, &lt;code&gt;mydocker exec&lt;/code&gt; adds your shell to the existing container’s namespaces, letting you run commands inside it.) The Chinese blog [89] illustrates this pattern clearly. The key idea is: &lt;em&gt;we fork a new process that points itself into the container’s namespaces and execs the command as if we were inside the container&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Container Lifecycle (&lt;code&gt;startContainer&lt;/code&gt;, &lt;code&gt;child&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Putting it all together, MyDocker’s container lifecycle roughly is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start&lt;/strong&gt;: User runs &lt;code&gt;mydocker run ...&lt;/code&gt;. The Go &lt;code&gt;main.go&lt;/code&gt; calls &lt;code&gt;startContainer(...)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;: In &lt;code&gt;startContainer&lt;/code&gt;, MyDocker creates a directory for the container under &lt;code&gt;/var/lib/mydocker/&amp;lt;id&amp;gt;&lt;/code&gt;. It unpacks the OCI image rootfs there (if not done already), creates cgroups, sets up network (bridge/veth), and prepares the command arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Clone (run)&lt;/strong&gt;: The code then does something like:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;exec&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/proc/self/exe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"child"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;commandArgs&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stderr&lt;/span&gt;
&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysProcAttr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SysProcAttr&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Cloneflags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CLONE_NEWUTS&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;CLONE_NEWPID&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;CLONE_NEWNET&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;CLONE_NEWNS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;UidMappings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;GidMappings&lt;/span&gt;&lt;span class="o"&gt;:&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="n"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// blocks until container process exits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This effectively forks into a &lt;strong&gt;child&lt;/strong&gt; process that will run &lt;code&gt;mydocker child ...&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Child setup&lt;/strong&gt;: In the &lt;code&gt;child()&lt;/code&gt; function inside Go, the process is now in fresh namespaces. It performs actions similar to Docker’s container init:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Calls `syscall.Chroot()` or `pivot_root()` to switch the root filesystem to the unpacked image.

- Applies mounts and volume binds (`syscall.Mount()`) for any `-v host:container` flags.

- Calls `net.SetupVeth()` to move one end of the veth into this namespace and bring up the network interface.

- Executes the container’s init process (e.g., `exec.Command("/bin/sh")`).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run&lt;/strong&gt;: The container process (PID 1 in its PID namespace) starts and runs user code. Meanwhile, the parent Go process (still the original CLI) waits (or returns immediately if detached).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stop&lt;/strong&gt;: When the container’s main process exits (e.g. you exit the shell), the child function returns. &lt;code&gt;startContainer&lt;/code&gt; (the parent) will then do cleanup: remove cgroups, delete metadata, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The code for &lt;code&gt;startContainer&lt;/code&gt; and &lt;code&gt;child&lt;/code&gt; in MyDocker is similar in spirit to many "from-scratch Docker" examples (e.g. [86]). For instance, the parent uses &lt;code&gt;exec.Command("/proc/self/exe", "child", …)&lt;/code&gt; to create the child. Inside &lt;code&gt;child&lt;/code&gt;, Go code uses syscalls (&lt;code&gt;Mount&lt;/code&gt;, &lt;code&gt;Chroot&lt;/code&gt;, &lt;code&gt;Sethostname&lt;/code&gt;, etc.) to finish setting up the namespace, then &lt;code&gt;exec.Command&lt;/code&gt; to run the actual command. Though we can’t cite the MyDocker source directly here, conceptually it follows the pattern above.&lt;/p&gt;
&lt;h3&gt;
  
  
  Networking
&lt;/h3&gt;

&lt;p&gt;By default, containers should be able to talk to each other and the outside world (on certain ports). MyDocker’s &lt;code&gt;network/&lt;/code&gt; package likely does the following (in Go, via the &lt;a href="https://github.com/vishvananda/netlink" rel="noopener noreferrer"&gt;vishvananda/netlink&lt;/a&gt; library or raw syscalls):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Ensure a Linux bridge exists (named &lt;code&gt;mydocker0&lt;/code&gt;). If not, create it with &lt;code&gt;ip link add name mydocker0 type bridge&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each new container, create a veth pair (e.g. &lt;code&gt;veth-host&lt;/code&gt; and &lt;code&gt;veth-container&lt;/code&gt;). Move &lt;code&gt;veth-container&lt;/code&gt; into the new namespace of the child (with &lt;code&gt;netlink.LinkSetNsFd&lt;/code&gt;) and rename it to &lt;code&gt;eth0&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bring up &lt;code&gt;eth0&lt;/code&gt; inside the container and assign it an IP (e.g. via &lt;code&gt;ip addr&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attach &lt;code&gt;veth-host&lt;/code&gt; to the &lt;code&gt;mydocker0&lt;/code&gt; bridge and bring it up on the host.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way, containers get an IP on the &lt;code&gt;mydocker0&lt;/code&gt; network, and host-side NAT (iptables MASQUERADE) handles outbound traffic and port mapping. MyDocker’s README mentions a &lt;em&gt;custom bridge network (&lt;code&gt;mydocker0&lt;/code&gt;) and veth pairs for network isolation&lt;/em&gt;. (In our blog, we won’t go into all the iptables details, but that’s how host ports get forwarded: the CLI probably calls &lt;code&gt;iptables -t nat&lt;/code&gt; rules so that &lt;code&gt;-p host:container&lt;/code&gt; flags forward TCP from the host port to the container’s IP:port.)&lt;/p&gt;
&lt;h3&gt;
  
  
  Image Handling and OCI Unpacking
&lt;/h3&gt;

&lt;p&gt;Container images (like &lt;code&gt;ubuntu:22.04&lt;/code&gt;) come in the OCI/Docker image format. MyDocker supports pulling and unpacking these images using the &lt;a href="https://github.com/opencontainers/umoci" rel="noopener noreferrer"&gt;&lt;code&gt;umoci&lt;/code&gt;&lt;/a&gt; tool. The &lt;code&gt;mydocker pull&lt;/code&gt; command likely shells out to &lt;code&gt;umoci pull&lt;/code&gt; or similar, then &lt;code&gt;umoci unpack&lt;/code&gt;. As &lt;a href="https://manpages.debian.org/testing/umoci/umoci-unpack.1.en.html" rel="noopener noreferrer"&gt;the umoci manual&lt;/a&gt; states: &lt;em&gt;“umoci unpack – Unpacks an OCI image tag into a runtime bundle”&lt;/em&gt;. In practice, MyDocker runs something like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;umoci unpack &lt;span class="nt"&gt;--image&lt;/span&gt; ubuntu:22.04 /var/lib/mydocker/images/ubuntu_22.04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This extracts the image layers and config into a directory that becomes the container’s root filesystem. MyDocker then stores this location (under &lt;code&gt;/var/lib/mydocker/&lt;/code&gt;) so that future &lt;code&gt;run&lt;/code&gt; commands can use the rootfs directly without repulling. The unpacked bundle includes &lt;code&gt;/rootfs&lt;/code&gt; with all files and a JSON config. MyDocker’s Go code then &lt;code&gt;chroot&lt;/code&gt;-es into that &lt;code&gt;/rootfs&lt;/code&gt; when starting a container.&lt;/p&gt;

&lt;p&gt;Using umoci (or a similar OCI utility) is important because it handles the layered filesystem format of images. Without overlay support, MyDocker unpacks into a single directory per image. The README cites &lt;em&gt;“Simple OCI image unpacking using &lt;code&gt;umoci&lt;/code&gt;”&lt;/em&gt; as a feature.&lt;/p&gt;
&lt;h3&gt;
  
  
  Volumes and Port Mappings
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Volumes (&lt;code&gt;-v&lt;/code&gt;)&lt;/strong&gt;: If the user specifies &lt;code&gt;-v /host/dir:/container/dir&lt;/code&gt;, MyDocker will mount a bind mount inside the container namespace. The Go code in &lt;code&gt;child()&lt;/code&gt; would do something like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/host/dir"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/container/dir"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MS_BIND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;after switching to the new root. This makes the host’s directory appear at the given path in the container. It relies on the mount namespace being isolated, so only the container sees the mount (the host’s filesystem is shared, but the namespace separates the mount list).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Port mappings (&lt;code&gt;-p&lt;/code&gt;)&lt;/strong&gt;: For &lt;code&gt;-p hostPort:containerPort&lt;/code&gt;, the runtime must forward network traffic. A simple approach: on the host, use &lt;code&gt;iptables&lt;/code&gt; to NAT traffic from &lt;code&gt;hostPort&lt;/code&gt; into the container’s IP and &lt;code&gt;containerPort&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; PREROUTING &lt;span class="nt"&gt;-p&lt;/span&gt; tcp &lt;span class="nt"&gt;--dport&lt;/span&gt; &amp;lt;hostPort&amp;gt; &lt;span class="nt"&gt;-j&lt;/span&gt; DNAT &lt;span class="nt"&gt;--to-destination&lt;/span&gt; &amp;lt;containerIP&amp;gt;:&amp;lt;containerPort&amp;gt;
iptables &lt;span class="nt"&gt;-t&lt;/span&gt; nat &lt;span class="nt"&gt;-A&lt;/span&gt; POSTROUTING &lt;span class="nt"&gt;-j&lt;/span&gt; MASQUERADE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This way, if a service inside the container listens on &lt;code&gt;containerPort&lt;/code&gt;, requests to &lt;code&gt;localhost:hostPort&lt;/code&gt; on the host will reach it. MyDocker’s implementation likely sets up such iptables rules automatically when starting the container, and removes them on stop. This achieves “port mapping” similar to Docker.&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%2Fpl9w5krg5y8h7yerw8ya.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%2Fpl9w5krg5y8h7yerw8ya.png" alt="MyDocker 1 Diagram 1"&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%2F34zozgijlgsgxi99yg8c.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%2F34zozgijlgsgxi99yg8c.png" alt="MyDocker 1 Diagram 2"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Diagrams
&lt;/h2&gt;

&lt;p&gt;Below are some visual aids (using PlantUML) to illustrate the architecture and isolation concepts. These diagrams are simplified schematics.&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%2Fbwoovdo7mhpzrclmrkeu.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%2Fbwoovdo7mhpzrclmrkeu.png" alt=" "&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%2Fkvxnt59ruasi5vwam0xb.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%2Fkvxnt59ruasi5vwam0xb.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These diagrams outline how the host CLI and services collaborate to create an isolated container process. In particular, the second diagram emphasizes that once the container process (&lt;code&gt;C&lt;/code&gt;) is created, it has its own namespace instances and cannot see the host’s unrelated processes or network stacks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started and Resources
&lt;/h2&gt;

&lt;p&gt;MyDocker is intended as a learning tool to explore container internals. It “demonstrates how containerization works under the hood” and helps you understand namespaces, cgroups, and image formats. You can try it out by following the &lt;a href="https://github.com/Ravikisha/MyDocker/blob/main/README.md" rel="noopener noreferrer"&gt;README instructions&lt;/a&gt;: for example, pull an image (&lt;code&gt;mydocker pull ubuntu:22.04&lt;/code&gt;) and run it (&lt;code&gt;mydocker run -it -v /data:/data -p 8080:80 ubuntu:22.04 bash&lt;/code&gt;) as shown in the usage examples. You’ll see your process isolated (check &lt;code&gt;ps&lt;/code&gt; and hostname inside the container, and network connectivity to the bridge).&lt;/p&gt;

&lt;p&gt;We encourage you to explore the &lt;a href="https://github.com/Ravikisha/MyDocker" rel="noopener noreferrer"&gt;Project Files&lt;/a&gt; (which includes source code and examples) and even extend it. Possible exercises include adding features like Dockerfile builds, overlayfs support, or enhanced networking. By tinkering with MyDocker’s code, you’ll gain a deep understanding of what happens in every &lt;code&gt;docker run&lt;/code&gt; command. Happy hacking and containerizing!&lt;/p&gt;

&lt;p&gt;Check out the github repo:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Ravikisha" rel="noopener noreferrer"&gt;
        Ravikisha
      &lt;/a&gt; / &lt;a href="https://github.com/Ravikisha/MyDocker" rel="noopener noreferrer"&gt;
        MyDocker
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      MyDocker is a lightweight container runtime built from scratch in Go that demonstrates how containerization works under the hood — similar to Docker but in a simplified form.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Ravikisha/MyDocker/./mydocker_docs/mydocker_banner.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FRavikisha%2FMyDocker%2F.%2Fmydocker_docs%2Fmydocker_banner.png" alt="MyDocker Banner"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🐳 MyDocker&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;MyDocker&lt;/strong&gt; is a lightweight container runtime built from scratch in Go that demonstrates how containerization works under the hood — similar to Docker but in a simplified form.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/ravikisha/mydocker" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Features&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Container process isolation using Linux namespaces (&lt;code&gt;UTS&lt;/code&gt;, &lt;code&gt;PID&lt;/code&gt;, &lt;code&gt;NET&lt;/code&gt;, &lt;code&gt;NS&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Resource control via cgroups (CPU &amp;amp; Memory)&lt;/li&gt;
&lt;li&gt;Volume mounting (&lt;code&gt;-v host:container&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Port mapping support (&lt;code&gt;-p host:container&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Simple OCI image unpacking using &lt;code&gt;umoci&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Container image pulling, listing, and execution&lt;/li&gt;
&lt;li&gt;Custom bridge network (&lt;code&gt;mydocker0&lt;/code&gt;) and veth pairs for network isolation&lt;/li&gt;
&lt;li&gt;Command-line interface similar to Docker (&lt;code&gt;run&lt;/code&gt;, &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;stop&lt;/code&gt;, &lt;code&gt;pull&lt;/code&gt;, &lt;code&gt;images&lt;/code&gt;, &lt;code&gt;version&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎯 Architecture&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Ravikisha/MyDocker/./mydocker_docs/diagram.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FRavikisha%2FMyDocker%2F.%2Fmydocker_docs%2Fdiagram.jpg" alt="Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📦 Installation&lt;/h2&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go 1.19+&lt;/li&gt;
&lt;li&gt;Root access (for namespace and networking)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;umoci&lt;/code&gt; tool installed and in &lt;code&gt;$PATH&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Linux OS (recommended: Ubuntu)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/ravikisha/mydocker.git
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; mydocker
go build -o mydocker main.go
sudo ./mydocker version&lt;/pre&gt;

&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Ravikisha/MyDocker" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Introducing RelaxLang: A Beginner-Friendly Programming Language</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Thu, 16 Jan 2025 19:30:05 +0000</pubDate>
      <link>https://dev.to/ravikishan/introducing-relaxlang-a-beginner-friendly-programming-language-33i9</link>
      <guid>https://dev.to/ravikishan/introducing-relaxlang-a-beginner-friendly-programming-language-33i9</guid>
      <description>&lt;p&gt;In the vast and ever-evolving world of programming languages, creating one from scratch is a feat that blends art, science, and a touch of magic. Today, I am excited to introduce &lt;strong&gt;RelaxLang&lt;/strong&gt;, a simple yet powerful interpreted programming language. Inspired by Robert Nystrom's &lt;em&gt;Crafting Interpreters&lt;/em&gt; and the Lox programming language, RelaxLang is designed to be accessible for beginners while being feature-rich for enthusiasts who want to dive deeper into language design and implementation.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why RelaxLang?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;RelaxLang stems from a vision to provide a lightweight, easy-to-understand programming language that serves as both a learning tool and a practical solution for basic scripting needs. Built with &lt;strong&gt;Java&lt;/strong&gt; and &lt;strong&gt;C&lt;/strong&gt;, it offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Typing:&lt;/strong&gt; Simplifies coding by inferring variable types at runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-Class Functions:&lt;/strong&gt; Enables functional programming paradigms by treating functions as first-class citizens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Classes and Inheritance:&lt;/strong&gt; Introduces object-oriented programming with a straightforward syntax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-In Standard Library:&lt;/strong&gt; Provides out-of-the-box utilities for string manipulation, array operations, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you're an aspiring developer eager to learn how programming languages work or a seasoned programmer seeking an educational tool, RelaxLang caters to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Architecture&lt;/strong&gt;
&lt;/h3&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%2Faamtspl73ex250i3uqkc.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%2Faamtspl73ex250i3uqkc.png" alt="RelaxLang Diagram" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Key Features of RelaxLang&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Dynamic Typing&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In RelaxLang, you don’t need to worry about specifying types for variables. The interpreter takes care of it, allowing you to focus on logic and creativity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var name = "RelaxLang";  // Automatically inferred as String
var version = 1.0;       // Automatically inferred as Float
var isActive = true;     // Automatically inferred as Boolean

print(name);            // Output: RelaxLang
print(version);         // Output: 1.0
print(isActive);        // Output: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. &lt;strong&gt;First-Class Functions&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Functions are versatile in RelaxLang. They can be assigned to variables, passed as arguments, and even returned from other functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun add(a, b) {
    return a + b;
}

var sum = add(5, 3);
print(sum);  // Output: 8

fun operate(func, x, y) {
    return func(x, y);
}

var result = operate(add, 10, 15);
print(result);  // Output: 25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. &lt;strong&gt;Classes and Inheritance&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;RelaxLang supports object-oriented programming, making it a great tool to understand and implement OOP concepts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Animal {
    var name;

    init(name) {
        this.name = name;
    }

    fun speak() {
        print(this.name + " makes a sound.");
    }
}

class Dog &amp;lt; Animal {
    fun speak() {
        print(this.name + " barks.");
    }
}

var myDog = Dog("Buddy");
myDog.speak();  // Output: Buddy barks.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. &lt;strong&gt;Control Flow&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;With intuitive &lt;code&gt;if-else&lt;/code&gt; statements and loops, you can control the flow of your programs effortlessly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var age = 18;

if (age &amp;lt; 18) {
    print("Minor");
} else {
    print("Adult");
}

for (var i = 0; i &amp;lt; 5; i = i + 1) {
    print(i);  // Output: 0 1 2 3 4
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;How to Get Started&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Prerequisites&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Ensure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java JDK 11 or later&lt;/strong&gt; (&lt;a href="https://www.oracle.com/java/technologies/javase-jdk11-downloads.html" rel="noopener noreferrer"&gt;Download here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;(Optional) &lt;strong&gt;Docker&lt;/strong&gt; for a containerized setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Installation&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Clone the Repository:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Ravikisha/RelaxLang.git
&lt;span class="nb"&gt;cd &lt;/span&gt;RelaxLang
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Compile the Source Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;javac src/&lt;span class="k"&gt;*&lt;/span&gt;.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;3. Running RelaxLang&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Using the JAR File:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; lox.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using Docker:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull ravikishan63392/relaxlang:lastest
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; ravikishan63392/relaxlang:lastest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Example Usage&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;RelaxLang scripts are simple to write and execute. For instance, here’s a script &lt;code&gt;example.rl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fun greet(name) {
    print("Hello, " + name + "!");
}

greet("World");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java &lt;span class="nt"&gt;-jar&lt;/span&gt; lox.jar example.rl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;The Technical Journey&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;RelaxLang’s implementation involves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lexical Analysis:&lt;/strong&gt; Breaking down source code into tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parsing:&lt;/strong&gt; Constructing an Abstract Syntax Tree (AST) from tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interpreting:&lt;/strong&gt; Executing the AST by traversing it node by node.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Developed in &lt;strong&gt;Java&lt;/strong&gt; for platform independence and in &lt;strong&gt;C&lt;/strong&gt; for low-level optimizations, RelaxLang’s design reflects a balance between simplicity and functionality.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Resources and Contributions&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Docker Image:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://hub.docker.com/repository/docker/ravikishan63392/relaxlang/" rel="noopener noreferrer"&gt;RelaxLang Docker Image&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;GitHub Repository:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/Ravikisha/RelaxLang" rel="noopener noreferrer"&gt;RelaxLang on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We welcome contributions! Whether it's bug fixes, feature requests, or documentation improvements, your input makes RelaxLang better. Please check out the contributing guidelines in the repository.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Final Thoughts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;RelaxLang is not just a programming language; it’s a journey into the heart of language design. By exploring its features, experimenting with scripts, and diving into its implementation, you can gain insights into how modern programming languages work.&lt;/p&gt;

&lt;p&gt;Give RelaxLang a try and embark on this exciting adventure. Let’s code, learn, and relax!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>learning</category>
      <category>java</category>
    </item>
    <item>
      <title>Building RelaxTube: A Scalable Video Transcoding and Streaming Application</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Tue, 14 Jan 2025 18:34:42 +0000</pubDate>
      <link>https://dev.to/ravikishan/building-relaxtube-a-scalable-video-transcoding-and-streaming-application-3i4a</link>
      <guid>https://dev.to/ravikishan/building-relaxtube-a-scalable-video-transcoding-and-streaming-application-3i4a</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;RelaxTube is a feature-rich and scalable application designed to demonstrate the workflow of video transcoding and streaming. The project highlights the use of modern technologies like Node.js, React, Kafka, FFmpeg, MongoDB, and Docker. It efficiently processes videos by transcoding them into multiple quality levels, segmenting them for smoother streaming, and generating thumbnail previews.&lt;/p&gt;

&lt;p&gt;This blog explores the architecture, key features, tech stack, installation, and potential enhancements for RelaxTube.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Video Transcoding&lt;/strong&gt;: Converts videos into multiple quality levels (360p, 480p, 720p, 1080p) using FFmpeg.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HLS Segmentation&lt;/strong&gt;: Generates video segments for efficient HTTP Live Streaming (HLS) playback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thumbnail Generation&lt;/strong&gt;: Automatically creates thumbnail previews for each uploaded video.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch Processing&lt;/strong&gt;: Supports concurrent video processing using Kafka message queues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable Design&lt;/strong&gt;: Built to handle increased loads and integrate with distributed systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage and Metadata&lt;/strong&gt;: Manages video files in local storage and metadata in MongoDB.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Project Architecture
&lt;/h2&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%2Fuys5b1yhux2j8dyfjim6.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%2Fuys5b1yhux2j8dyfjim6.png" alt="Diagram" width="759" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend (React)&lt;/strong&gt;: Provides a user-friendly interface for video uploads, management, and playback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend (Node.js with Express)&lt;/strong&gt;: Handles API requests, video processing workflows, and communication with Kafka.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kafka&lt;/strong&gt;: Manages message queues for efficient batch processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transcoding Service (FFmpeg)&lt;/strong&gt;: Handles video transcoding, segmentation, and thumbnail creation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MongoDB&lt;/strong&gt;: Stores metadata like video information, quality levels, and thumbnails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File Storage&lt;/strong&gt;: Stores processed video files and thumbnails locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt;: Backend logic and API endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt;: Frontend for user interaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kafka&lt;/strong&gt;: Manages distributed message queues for scalability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FFmpeg&lt;/strong&gt;: Performs video transcoding, segmentation, and thumbnail generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MongoDB&lt;/strong&gt;: Stores metadata and provides quick access to processed data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: Ensures easy setup and consistent environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TailwindCSS&lt;/strong&gt;: Enhances the frontend with modern styling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation and Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; (v16 or higher).&lt;/li&gt;
&lt;li&gt;Clone the repository:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/Ravikisha/RelaxTube.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;RelaxTube
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Steps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run Docker Compose&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Dependencies&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;cd &lt;/span&gt;frontend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install
   cd&lt;/span&gt; ../backend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install
   cd&lt;/span&gt; ../transcoding-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start Services&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;backend
 npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Frontend:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;frontend
 npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Transcoding Service:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;transcoding-service
 npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Access the Application&lt;/strong&gt;
Open your browser and navigate to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Upload Videos&lt;/strong&gt;: Users can upload videos through the frontend interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Processing&lt;/strong&gt;: The backend processes the videos by:

&lt;ul&gt;
&lt;li&gt;Transcoding them to multiple quality levels.&lt;/li&gt;
&lt;li&gt;Segmenting videos for HLS playback.&lt;/li&gt;
&lt;li&gt;Generating thumbnails.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming&lt;/strong&gt;: Processed videos are available for streaming via the frontend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch Processing&lt;/strong&gt;: Upload multiple videos for concurrent processing.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Screenshots
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Homepage
&lt;/h3&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%2F6ev1atpvdy5qi05ee52k.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%2F6ev1atpvdy5qi05ee52k.png" alt="Home Page" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Video Playback
&lt;/h3&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%2Fndzn342bft8q5f205oxr.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%2Fndzn342bft8q5f205oxr.png" alt="Video Playback" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Quality Selection
&lt;/h3&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%2Fu66grti6f967yl16jw2l.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%2Fu66grti6f967yl16jw2l.png" alt="Quality" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Upload Interface
&lt;/h3&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%2Fyf9manf3dw4cqlvlkh7g.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%2Fyf9manf3dw4cqlvlkh7g.png" alt="Upload" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch Upload
&lt;/h3&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%2F40imn37cy2sdk904jkbm.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%2F40imn37cy2sdk904jkbm.png" alt="Batch Upload" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scalability Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Batch Processing&lt;/strong&gt;: Process multiple videos simultaneously using Kafka.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distributed Workers&lt;/strong&gt;: Scale horizontally by adding workers for transcoding tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancing&lt;/strong&gt;: Distribute incoming requests across multiple backend servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Storage&lt;/strong&gt;: Potential integration with AWS S3 or Google Cloud Storage for large-scale storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring&lt;/strong&gt;: Use tools like Prometheus or Grafana for real-time monitoring and performance tracking.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Future Enhancements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Cloud deployment for global access and scalability.&lt;/li&gt;
&lt;li&gt;Advanced analytics for tracking user interactions and video performance.&lt;/li&gt;
&lt;li&gt;User authentication and access control.&lt;/li&gt;
&lt;li&gt;Caching mechanisms for faster access to frequently requested content.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;We welcome contributions to RelaxTube! Feel free to submit pull requests, report issues, or suggest new features.&lt;/p&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;RelaxTube is licensed under the MIT License. See the &lt;a href="https://github.com/Ravikisha/RelaxTube/blob/main/LICENSE" rel="noopener noreferrer"&gt;LICENSE&lt;/a&gt; file for details.&lt;/p&gt;




&lt;p&gt;Start exploring RelaxTube by visiting the &lt;a href="https://github.com/Ravikisha/RelaxTube" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>mern</category>
      <category>kafka</category>
      <category>systemdesign</category>
      <category>docker</category>
    </item>
    <item>
      <title>Building Scalable Web Applications with Microfrontends: A Detailed Walkthrough of Microfrontend Blog</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Sun, 29 Dec 2024 14:23:36 +0000</pubDate>
      <link>https://dev.to/ravikishan/building-scalable-web-applications-with-microfrontends-a-detailed-walkthrough-of-microfrontend-blog-2hlp</link>
      <guid>https://dev.to/ravikishan/building-scalable-web-applications-with-microfrontends-a-detailed-walkthrough-of-microfrontend-blog-2hlp</guid>
      <description>&lt;h4&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In the rapidly evolving world of web development, creating scalable, maintainable, and modular applications is more important than ever. Enter &lt;strong&gt;microfrontend architecture&lt;/strong&gt;—a game-changing approach that divides a monolithic frontend into smaller, independently deployable pieces. &lt;/p&gt;

&lt;p&gt;This blog introduces &lt;strong&gt;Microfrontend Blog&lt;/strong&gt;, a real-world implementation of microfrontends built using cutting-edge technologies like &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;TailwindCSS&lt;/strong&gt;, &lt;strong&gt;Clerk&lt;/strong&gt;, &lt;strong&gt;Module Federation&lt;/strong&gt;, and &lt;strong&gt;Firebase Firestore&lt;/strong&gt;. Whether you're an experienced developer or just getting started with microfrontends, this project is a comprehensive guide to building modular web applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/Ravikisha/Microfrontend-Blog" rel="noopener noreferrer"&gt;Microfrontend Blog&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Project Overview&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Microfrontend Blog&lt;/strong&gt; is a blogging platform designed to demonstrate the power of microfrontend architecture. It splits the application into five key modules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Auth Microfrontend&lt;/strong&gt;: Handles user authentication using &lt;strong&gt;Clerk&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard Microfrontend&lt;/strong&gt;: Allows users to create, edit, and manage blogs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Viewer Microfrontend&lt;/strong&gt;: Displays blogs with comment functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared Components&lt;/strong&gt;: A library of reusable components like headers, footers, and blog cards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container&lt;/strong&gt;: Orchestrates the integration of all microfrontends.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By adopting &lt;strong&gt;Module Federation&lt;/strong&gt;, each microfrontend is developed and deployed independently, enabling seamless collaboration across teams and simplifying the scaling process.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Features&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt;: Secure login and signup with Clerk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blog Management&lt;/strong&gt;: A rich dashboard for managing blogs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blog Viewing&lt;/strong&gt;: Interactive blog display with a comments section.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive UI&lt;/strong&gt;: Styled with &lt;strong&gt;TailwindCSS&lt;/strong&gt; for consistency across devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Independent deployment of microfrontends.&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Technologies Used&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt;: The foundation for building the UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TailwindCSS&lt;/strong&gt;: A utility-first CSS framework for modern designs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clerk&lt;/strong&gt;: A robust authentication library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firebase Firestore&lt;/strong&gt;: Cloud-based database for blog storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Module Federation&lt;/strong&gt;: Simplifies microfrontend integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webpack&lt;/strong&gt;: Efficient module bundler for development and production.&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Architecture Diagram&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The architecture demonstrates the interaction between microfrontends, the container, and backend services:&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%2F02gyzxyvl5w700dlc6hv.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%2F02gyzxyvl5w700dlc6hv.png" alt="Microfrontend Diagram" width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Getting Started&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;strong&gt;Node.js&lt;/strong&gt; (v16+).&lt;/li&gt;
&lt;li&gt;Clone the repository:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  git clone https://github.com/Ravikisha/Microfrontend-Blog.git
  &lt;span class="nb"&gt;cd &lt;/span&gt;Microfrontend-Blog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Install Dependencies&lt;/strong&gt;&lt;br&gt;
For each microfrontend and shared components, run:&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;microfrontend-folder&amp;gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Start the Development Server&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Access the Application&lt;/strong&gt;&lt;br&gt;
Visit &lt;a href="http://localhost:3005" rel="noopener noreferrer"&gt;http://localhost:3005&lt;/a&gt; to view the application.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Screenshots&lt;/strong&gt;
&lt;/h4&gt;

&lt;h2&gt;
  
  
  Screenshots
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Home Page&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2Fg1ihk0n6scjtzecwo7w2.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%2Fg1ihk0n6scjtzecwo7w2.png" alt="Home Page" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Login Page&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2Fw9fm8d503ne5ayhd4vxn.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%2Fw9fm8d503ne5ayhd4vxn.png" alt="Login Page" width="682" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create Blog&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2Fiob4hn96c1o8pbnyco5r.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%2Fiob4hn96c1o8pbnyco5r.png" alt="Create Blog" width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;View Blog&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2F6xjajfxylcpg473y4f2p.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%2F6xjajfxylcpg473y4f2p.png" alt="Content 1" width="800" height="367"&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%2Fscm418y6bfy6i7t2l5fv.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%2Fscm418y6bfy6i7t2l5fv.png" alt="Content 2" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MicroFrontend Screenshots
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Auth Microfrontend&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2Fyriixnzb5cdfqgpuddzu.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%2Fyriixnzb5cdfqgpuddzu.png" alt="Auth Mfe" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard Microfrontend&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2Fpj3iutrlxb5591vlozm4.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%2Fpj3iutrlxb5591vlozm4.png" alt="Dashboard mfe" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Viewer Microfrontend&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2F1jedmxrkmgk5vznhq4uh.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%2F1jedmxrkmgk5vznhq4uh.png" alt="Viewer Mfe" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Shared Components&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2F98c5nah5y2pviu5qfa3n.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%2F98c5nah5y2pviu5qfa3n.png" alt="Shared mfe" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Container&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&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%2Fypeiuatln3m8qedzjp1o.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%2Fypeiuatln3m8qedzjp1o.png" alt="Container mfe" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Key Benefits of Microfrontend Architecture&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Independent Development&lt;/strong&gt;: Teams can work on different microfrontends without stepping on each other's toes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Easily scale individual modules based on demand.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusability&lt;/strong&gt;: Shared components streamline development and ensure design consistency.&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The &lt;strong&gt;Microfrontend Blog&lt;/strong&gt; project serves as a practical example of how microfrontend architecture can simplify development and improve scalability. With technologies like &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;TailwindCSS&lt;/strong&gt;, and &lt;strong&gt;Module Federation&lt;/strong&gt;, developers can create robust and maintainable applications that meet modern web development demands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explore the code and start building your modular applications today!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/Ravikisha/Microfrontend-Blog" rel="noopener noreferrer"&gt;Microfrontend Blog&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Would you like me to add more details, such as common troubleshooting tips or deeper dives into individual microfrontends?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introducing Stylesnap: Optimize Your CSS Like Never Before</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Sun, 29 Dec 2024 14:04:56 +0000</pubDate>
      <link>https://dev.to/ravikishan/introducing-stylesnap-optimize-your-css-like-never-before-508f</link>
      <guid>https://dev.to/ravikishan/introducing-stylesnap-optimize-your-css-like-never-before-508f</guid>
      <description>&lt;p&gt;In the ever-evolving world of web development, efficiency and optimization are paramount. Meet &lt;strong&gt;Stylesnap&lt;/strong&gt;, a cutting-edge solution for CSS optimization that simplifies your workflow and boosts performance. Designed for developers, this handy tool minimizes your CSS files by analyzing your project’s content and retaining only the styles you truly need.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;What is Stylesnap?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Stylesnap is an NPX package tailored for modern web development. It scans your codebase—HTML, JSX, or any supported files—and generates a lightweight, optimized CSS file that eliminates unused styles. Whether you're using popular frameworks like Bootstrap, TailwindCSS, or custom CSS, Stylesnap has you covered.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Key Features&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Selective CSS Extraction&lt;/strong&gt;: Extracts only the required class names, tags, and selectors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework Compatibility&lt;/strong&gt;: Works seamlessly with CSS frameworks or custom styles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minification&lt;/strong&gt;: Automatically minifies the generated CSS for improved performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Configurations&lt;/strong&gt;: Offers a customizable workflow using &lt;code&gt;stylesnap.config.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command-Line Simplicity&lt;/strong&gt;: Easy-to-use CLI for quick integration.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why Choose Stylesnap?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Performance&lt;/strong&gt;: Smaller CSS files mean faster page loads and better user experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Eliminates unused CSS, making your stylesheets cleaner and easier to manage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Compatible with various frameworks and custom setups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer-Friendly&lt;/strong&gt;: Simple installation, intuitive CLI options, and detailed documentation.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Getting Started&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Installation&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Use npm to install Stylesnap as a development dependency:&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;stylesnap &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or run it directly with NPX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx stylesnap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  &lt;strong&gt;Usage&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Stylesnap’s CLI makes it easy to optimize your CSS. Here’s a quick example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialize Configuration&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npx stylesnap &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a &lt;code&gt;stylesnap.config.json&lt;/code&gt; file in your project.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Update Configuration&lt;/strong&gt;:
Edit the file to suit your project’s needs:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"content"&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;"./src/**/*.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/**/*.jsx"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"css"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./src/styles.css"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"output"&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/optimized.css"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"minify"&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="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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run Stylesnap&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npx stylesnap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your optimized CSS will be saved at the specified output location.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Real-World Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By using Stylesnap, you’ll see immediate improvements in your development and deployment process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faster Load Times&lt;/strong&gt;: Reduced CSS file size enhances website speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smaller Builds&lt;/strong&gt;: Ideal for production environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlined Debugging&lt;/strong&gt;: With unused CSS eliminated, debugging becomes simpler.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Links&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/Ravikisha/stylesnap" rel="noopener noreferrer"&gt;https://github.com/Ravikisha/stylesnap&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPM Package&lt;/strong&gt;: &lt;a href="https://www.npmjs.com/package/stylesnap" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/stylesnap&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Contribute&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Stylesnap is open-source, and contributions are welcome! If you encounter any issues or have ideas for improvement, feel free to open an issue or submit a pull request.&lt;/p&gt;




&lt;p&gt;Start optimizing your CSS today with Stylesnap! 🚀 Streamline your workflow, boost performance, and take your web development projects to the next level.&lt;/p&gt;

</description>
      <category>css</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A Comprehensive Guide to Building a Single Sign-On (SSO) Gateway with Node.js</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Sun, 22 Dec 2024 17:13:18 +0000</pubDate>
      <link>https://dev.to/ravikishan/a-comprehensive-guide-to-building-a-single-sign-on-sso-gateway-with-nodejs-4lj4</link>
      <guid>https://dev.to/ravikishan/a-comprehensive-guide-to-building-a-single-sign-on-sso-gateway-with-nodejs-4lj4</guid>
      <description>&lt;p&gt;Single Sign-On (SSO) systems have become critical in today's interconnected application ecosystems. By allowing users to log in once and access multiple applications seamlessly, SSO simplifies authentication, enhances user experience, and bolsters security. This blog dives into the implementation of an SSO Gateway using Node.js, Express, and MongoDB, guiding you through its features, architecture, setup, and best practices.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;What is a Single Sign-On Gateway?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;An SSO Gateway is a centralized authentication system where users authenticate once and gain access to multiple interconnected applications without needing to reauthenticate. The Node-SSO-Gateway project demonstrates a robust yet simple implementation of such a system.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Key Features of the Node-SSO-Gateway&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Centralized Authentication&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users log in via a single SSO server, eliminating the need for multiple logins.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Token-Based Authorization&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secure, stateless communication between the SSO server and consumer applications via JSON Web Tokens (JWT).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cross-Domain Session Management&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintain seamless user sessions across multiple applications and domains.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MongoDB Integration&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Secure storage of user credentials with robust password hashing (e.g., bcrypt).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dynamic Consumer App Registration&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumer applications can dynamically register themselves with the SSO server for authentication.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Logout Functionality&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports global and local session termination for enhanced security.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;System Architecture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The system is divided into three primary components:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SSO Server&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The central hub that authenticates users, manages sessions, and issues JWT tokens.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consumer Applications (Clients)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Applications relying on the SSO server for authentication. Each client establishes a local session after verifying the token.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
A database backend to securely store user data, including email and hashed passwords.  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Architecture Diagram
&lt;/h4&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%2Fczja9mczemlqg0na73ct.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%2Fczja9mczemlqg0na73ct.png" alt="SSO Diagram" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;How Does It Work?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User Login&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users log in through the SSO server. Upon successful authentication, the server issues a JWT token and redirects the user to the desired consumer app.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Token Validation&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumer apps verify the JWT token with the SSO server before granting access to protected resources.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Session Management&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both global (SSO server) and local (consumer app) sessions are managed, ensuring secure and consistent access.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Logout&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users can log out from the SSO server, terminating the global session, or from a consumer app, terminating the local session.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Setting Up the Node-SSO-Gateway&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. Prerequisites&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Node.js and npm installed.
&lt;/li&gt;
&lt;li&gt;MongoDB instance running (local or cloud-based).
&lt;/li&gt;
&lt;li&gt;Basic knowledge of JWT, Express, and MongoDB.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. Clone the Repository&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Ravikisha/Node-SSO-Gateway.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Node-SSO-Gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;3. Install Dependencies&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Navigate to the root directory of each component and install the required packages.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For the SSO Server&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For Consumer Applications&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c"&gt;# In another terminal&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;client2
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;4. Configure MongoDB&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in both the SSO Server and consumer apps with the following content:&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="nv"&gt;MONGODB_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mongodb://localhost:27017/sso-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;5. Start the Applications&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Start the SSO Server:&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;server
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the consumer apps:&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;client1
npm run dev

&lt;span class="c"&gt;# In another terminal&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;client2
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;6. Test the System&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Visit &lt;code&gt;http://localhost:3000&lt;/code&gt; to access the SSO server login page.
&lt;/li&gt;
&lt;li&gt;Successfully log in to be redirected to consumer apps (&lt;code&gt;http://localhost:3001&lt;/code&gt; and &lt;code&gt;http://localhost:3002&lt;/code&gt;).
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Adding New Consumer Applications&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create a new app following the structure of &lt;code&gt;client1&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Register the app’s domain in the SSO Server’s &lt;code&gt;allowedOrigin&lt;/code&gt; configuration.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allowedOrigin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3001&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3002&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3003&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Redirect authentication requests to the SSO Server.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Security Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HTTPS Everywhere&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use HTTPS in production to ensure encrypted communication.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Secure JWT Storage&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store JWT securely, preferably in HTTP-only cookies, to prevent XSS attacks.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Validate Origins&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate consumer app origins to prevent unauthorized requests.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Password Hashing&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use strong hashing algorithms like bcrypt for storing user passwords.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Logout Functionality&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Local Logout&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removes the session from the consumer app only.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Global Logout&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terminates the session on the SSO Server, logging the user out from all consumer apps.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Screenshots&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Login Page
&lt;/h4&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%2Fhm0a2jqxk69erwfvczie.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%2Fhm0a2jqxk69erwfvczie.png" alt="SSO Login Page" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  SSO Server Page
&lt;/h4&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%2Ftzxr0ayl3de773y95okq.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%2Ftzxr0ayl3de773y95okq.png" alt="SSO Server Page" width="800" height="59"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h4&gt;
  
  
  Consumer Application (Client1)
&lt;/h4&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%2Fbq5k5f1pqvcfinoir7gw.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%2Fbq5k5f1pqvcfinoir7gw.png" alt="SSO Client 1" width="800" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Consumer Application (Client2)
&lt;/h4&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%2Fyfghy9jk9t1zwqykux6c.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%2Fyfghy9jk9t1zwqykux6c.png" alt="SSO Client 2" width="800" height="142"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;The Node-SSO-Gateway project offers a secure and scalable solution for centralized authentication across multiple applications. By leveraging modern web technologies like Node.js, Express, and JWT, the system ensures a seamless user experience and robust security. Whether you're building a microservices-based architecture or integrating multiple platforms, this SSO solution is a solid foundation for managing authentication effectively.  &lt;/p&gt;

&lt;p&gt;Explore the repository &lt;a href="https://github.com/Ravikisha/Node-SSO-Gateway" rel="noopener noreferrer"&gt;here&lt;/a&gt; and get started with centralized authentication today!&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>node</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a Feature-Rich Load Balancer in TypeScript: A Detailed Overview</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Sun, 22 Dec 2024 16:45:02 +0000</pubDate>
      <link>https://dev.to/ravikishan/building-a-feature-rich-load-balancer-in-typescript-a-detailed-overview-1f4f</link>
      <guid>https://dev.to/ravikishan/building-a-feature-rich-load-balancer-in-typescript-a-detailed-overview-1f4f</guid>
      <description>&lt;p&gt;Load balancers are essential components of modern distributed systems, ensuring scalability, fault tolerance, and optimal resource utilization. In this blog, we’ll explore the development and capabilities of a custom &lt;strong&gt;Load Balancer Implementation in TypeScript&lt;/strong&gt;—a project that combines advanced load-balancing algorithms, health checks, self-healing mechanisms, and webhook notifications. This implementation mirrors the functionality of industry-standard tools like &lt;strong&gt;NGINX&lt;/strong&gt; and &lt;strong&gt;HAProxy&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  GitHub Repository
&lt;/h4&gt;

&lt;p&gt;You can explore the complete project on GitHub: &lt;a href="https://github.com/Ravikisha/Load-Balancer-Implementation" rel="noopener noreferrer"&gt;Load Balancer Implementation&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Easy Configuration:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Configure all aspects of the load balancer through a &lt;code&gt;config.json&lt;/code&gt; file. This includes backend server details, health check intervals, and load-balancing algorithms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Load Balancing Algorithms:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Random:&lt;/strong&gt; Requests are sent to a randomly selected backend server.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Round-Robin:&lt;/strong&gt; Requests are distributed sequentially among backend servers.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weighted Round-Robin:&lt;/strong&gt; Backend servers are prioritized based on assigned weights.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Health Checks:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Periodic pings to backend servers ensure only healthy servers receive traffic. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-Healing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Automatically attempts to recover downed servers, with a configurable success rate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Retries and Redirects:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Failed requests are retried on alternative healthy servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Webhook Alerts:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Notify administrators of server failures via custom webhook triggers. Alerts include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Individual server failures.&lt;/li&gt;
&lt;li&gt;Total backend server failure.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The modular design allows for easy addition or removal of backend servers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;The repository contains the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend Server Simulation:&lt;/strong&gt; Simulates multiple backend servers for load balancing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancer Core:&lt;/strong&gt; Manages traffic, health checks, retries, and notifications.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration File:&lt;/strong&gt; Allows users to define the behavior of the load balancer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fdocs%2Fposter.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/.%2Fdocs%2Fposter.png" alt="Poster" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;strong&gt;Node.js&lt;/strong&gt; and &lt;strong&gt;npm&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Clone the repository:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone https://github.com/Ravikisha/Load-Balancer-Implementation.git
   &lt;span class="nb"&gt;cd &lt;/span&gt;Load-Balancer-Implementation
   npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Running the Application
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start Backend Servers:&lt;/strong&gt;
Run multiple backend servers on different ports using the command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npm run dev:be 8081
   npm run dev:be 8082
   npm run dev:be 8083
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Launch the Load Balancer:&lt;/strong&gt;
Start the load balancer on the specified port:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npm run dev:lb 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Send Requests:&lt;/strong&gt;
Use a tool like Postman or Curl to send HTTP requests to the load balancer at &lt;code&gt;http://localhost:8000&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Testing and Monitoring
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Simulate Backend Server Failures:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kill a backend server process.&lt;/li&gt;
&lt;li&gt;Observe automatic request redirection to other healthy servers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Webhook Alerts:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure a webhook URL in &lt;code&gt;config.json&lt;/code&gt; for real-time alerts.&lt;/li&gt;
&lt;li&gt;Use services like &lt;a href="https://typedwebhook.tools/" rel="noopener noreferrer"&gt;Typed Webhook&lt;/a&gt; to test notifications.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Self-Healing:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the logs for attempts to restart failed servers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Configuration Options
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;config.json&lt;/code&gt; file governs the behavior of the load balancer. Key parameters include:&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;"lbPORT"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_lbAlgo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"be_servers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8081"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8082"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"domain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8083"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"be_retries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"health_check_interval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"send_alert_webhook"&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://webhook.site/your-webhook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"enableSelfHealing"&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="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;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;_lbAlgo&lt;/code&gt;&lt;/strong&gt;: Choose between &lt;code&gt;rand&lt;/code&gt;, &lt;code&gt;rr&lt;/code&gt;, or &lt;code&gt;wrr&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;be_servers&lt;/code&gt;&lt;/strong&gt;: Define backend servers and their weights.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;send_alert_webhook&lt;/code&gt;&lt;/strong&gt;: Specify a webhook URL for notifications.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;enableSelfHealing&lt;/code&gt;&lt;/strong&gt;: Enable or disable server recovery attempts.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Insights and Learning Outcomes
&lt;/h2&gt;

&lt;p&gt;Developing this load balancer provided insights into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traffic Distribution Techniques:&lt;/strong&gt; Understanding how different algorithms impact performance and fairness.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fault Tolerance:&lt;/strong&gt; Designing systems that gracefully handle failures and recover automatically.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerting Mechanisms:&lt;/strong&gt; Using webhooks to keep administrators informed in real-time.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration Management:&lt;/strong&gt; Simplifying user experience through JSON-based settings.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Challenges and Future Scope
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Challenges:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ensuring low latency during health checks and retries.&lt;/li&gt;
&lt;li&gt;Managing detached processes spawned during self-healing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Future Enhancements:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Health Checks:&lt;/strong&gt; Add support for more complex health-check mechanisms.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL/TLS Support:&lt;/strong&gt; Enable secure communication between clients and backend servers.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Scaling:&lt;/strong&gt; Integrate with cloud APIs to dynamically scale backend server pools.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;This project demonstrates how a TypeScript-based load balancer can achieve features similar to enterprise-grade solutions like &lt;strong&gt;NGINX&lt;/strong&gt; or &lt;strong&gt;AWS ELB&lt;/strong&gt;. With robust fault tolerance, advanced load-balancing algorithms, and real-time alerting, this implementation serves as a practical example for developers looking to understand the inner workings of load balancers.&lt;/p&gt;

&lt;p&gt;Explore the project on &lt;a href="https://github.com/Ravikisha/Load-Balancer-Implementation" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, try it out, and contribute to its future enhancements!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>cloud</category>
      <category>aws</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Introducing GitaVerse: Access Bhagavad Gita Verses Programmatically 🚀</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Tue, 17 Dec 2024 15:55:10 +0000</pubDate>
      <link>https://dev.to/ravikishan/introducing-gitaverse-access-bhagavad-gita-verses-programmatically-53p1</link>
      <guid>https://dev.to/ravikishan/introducing-gitaverse-access-bhagavad-gita-verses-programmatically-53p1</guid>
      <description>&lt;p&gt;In the world of modern development, spiritual and literary texts can be made more accessible to developers through clean APIs and libraries. &lt;strong&gt;GitaVerse&lt;/strong&gt; is a modern TypeScript library that enables you to access, explore, and retrieve shlokas (verses) from the Bhagavad Gita with ease.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 What is GitaVerse?
&lt;/h2&gt;

&lt;p&gt;GitaVerse is a TypeScript-based NPM library that allows developers to programmatically fetch the &lt;strong&gt;Bhagavad Gita's verses&lt;/strong&gt; (shlokas), including translations, synonyms, and original Devanagari text.&lt;/p&gt;

&lt;p&gt;The Bhagavad Gita is a profound Hindu scripture consisting of 700 verses across &lt;strong&gt;18 chapters&lt;/strong&gt;. With GitaVerse, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve individual verses based on &lt;strong&gt;Chapter&lt;/strong&gt; and &lt;strong&gt;Verse number&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Fetch all shlokas in a specific chapter.&lt;/li&gt;
&lt;li&gt;Access translations, synonyms, and meanings in a structured format.&lt;/li&gt;
&lt;li&gt;Build spiritual apps, educational tools, or study tools effortlessly.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Features of GitaVerse
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Fetch Any Shloka&lt;/strong&gt;: Get verses from any chapter with full details.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Detailed Information&lt;/strong&gt;: Includes Devanagari text, verse translations, synonyms, and multiple meanings.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Organized Data&lt;/strong&gt;: All data is structured and typed with TypeScript interfaces for ease of use.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Easy-to-Use API&lt;/strong&gt;: Clean class-based methods for developers.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Lightweight&lt;/strong&gt;: Minimal dependencies for faster integration.&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;TypeScript Support&lt;/strong&gt;: Full type safety for robust development.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📥 Installation
&lt;/h2&gt;

&lt;p&gt;You can install &lt;strong&gt;GitaVerse&lt;/strong&gt; using &lt;strong&gt;npm&lt;/strong&gt; or &lt;strong&gt;yarn&lt;/strong&gt;:&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;gitaverse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔧 How to Use GitaVerse
&lt;/h2&gt;

&lt;p&gt;Here’s a quick guide on how you can use the &lt;strong&gt;GitaVerse&lt;/strong&gt; library.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Import GitaVerse and Initialize
&lt;/h3&gt;

&lt;p&gt;Start by importing the &lt;code&gt;GitaLibrary&lt;/code&gt; class and initializing it:&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;GitaLibrary&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;gitaverse&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;gita&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GitaLibrary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Fetch Metadata About the Bhagavad Gita
&lt;/h3&gt;

&lt;p&gt;Get an overview of the Bhagavad Gita, such as the total chapters and verses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gita&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDescription&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/*
Output:
{
  title: "Bhagavad Gita",
  description: "The Bhagavad Gita, often referred to as the Gita, is a 700-verse Hindu scripture that is part of the Indian epic Mahabharata.",
  totalChapters: 18,
  totalVerses: 700
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Fetch All Shlokas in a Chapter
&lt;/h3&gt;

&lt;p&gt;To retrieve all the verses from a specific chapter, use &lt;code&gt;getChapter()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chapter1Shlokas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gita&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getChapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;chapter1Shlokas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;shloka&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shloka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSummary&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;
  
  
  4. Fetch a Specific Shloka
&lt;/h3&gt;

&lt;p&gt;Fetch a specific shloka using &lt;strong&gt;chapter number&lt;/strong&gt; and &lt;strong&gt;verse number&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shloka&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gita&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getShloka&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shloka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSummary&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="cm"&gt;/*
Output:
{
  chapter: "1",
  verse: "1",
  devanagari: "धृतराष्ट्र उवाच...",
  verseText: "Dhritarashtra said...",
  synonyms: "Dhritarashtra - King Dhritarashtra...",
  translation: "King Dhritarashtra inquired...",
  meaning: ["Literal meaning of the verse...", "Spiritual significance..."]
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. Fetch All Shlokas Grouped by Chapters
&lt;/h3&gt;

&lt;p&gt;If you want to get all verses organized by chapters, use &lt;code&gt;getAllVerses()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allVerses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gita&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllVerses&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;allVerses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;chapter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`Chapter &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;chapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getShlokas&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; Shlokas available`&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;h2&gt;
  
  
  📚 API Methods Overview
&lt;/h2&gt;

&lt;p&gt;Here’s a quick overview of the available methods:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;GitaLibrary&lt;/code&gt; Methods:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getDescription()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get metadata about the Gita.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getChapter(chapter)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch all shlokas in a specific chapter.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getShloka(chapter, verse)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieve a specific shloka by chapter &amp;amp; verse.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getAllVerses()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch all shlokas grouped by chapters.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;GitaShloka&lt;/code&gt; Methods:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getSummary()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieve a summary of the shloka details.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getDevanagari()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get the Devanagari text of the verse.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getTranslation()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get the verse translation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getMeaning()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get multiple meanings of the verse.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🛠 Use Cases
&lt;/h2&gt;

&lt;p&gt;Here are a few ideas for integrating GitaVerse into your projects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spiritual Apps&lt;/strong&gt;: Build apps to display Gita shlokas with translations and explanations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Study Tools&lt;/strong&gt;: Develop tools for students to explore and understand the Bhagavad Gita.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIs&lt;/strong&gt;: Serve Gita data through REST APIs for web or mobile apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personal Projects&lt;/strong&gt;: Use it for personal study and exploration of the Gita.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🌐 Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NPM Package&lt;/strong&gt;: &lt;a href="https://www.npmjs.com/package/gitaverse" rel="noopener noreferrer"&gt;gitaverse on npm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/Ravikisha/GitaVerse/" rel="noopener noreferrer"&gt;GitaVerse on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤝 Contributing
&lt;/h2&gt;

&lt;p&gt;We welcome contributions! If you'd like to add features or fix issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork the repository from &lt;a href="https://github.com/Ravikisha/GitaVerse/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create a feature branch.&lt;/li&gt;
&lt;li&gt;Submit a pull request.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For any suggestions or bugs, feel free to raise an issue.&lt;/p&gt;




&lt;h2&gt;
  
  
  📄 License
&lt;/h2&gt;

&lt;p&gt;This project is licensed under the MIT License. See the &lt;a href="https://github.com/Ravikisha/GitaVerse/blob/main/LICENSE" rel="noopener noreferrer"&gt;LICENSE&lt;/a&gt; file for more details.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ Final Thoughts
&lt;/h2&gt;

&lt;p&gt;With &lt;strong&gt;GitaVerse&lt;/strong&gt;, exploring the timeless wisdom of the Bhagavad Gita becomes simple and developer-friendly. Whether you're building spiritual apps, study tools, or personal projects, GitaVerse provides everything you need to programmatically access and share the Gita's teachings.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"You have the right to work, but never to the fruit of work."&lt;/em&gt;&lt;br&gt;&lt;br&gt;
— Bhagavad Gita (Chapter 2, Verse 47)&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Start Exploring the Gita Today with GitaVerse!&lt;/strong&gt; 🌟&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/gitaverse" rel="noopener noreferrer"&gt;&lt;strong&gt;Install Now&lt;/strong&gt;&lt;/a&gt;  &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Introducing NexaPHP: A Lightweight MVC PHP Framework</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Thu, 07 Nov 2024 16:54:24 +0000</pubDate>
      <link>https://dev.to/ravikishan/introducing-nexaphp-a-lightweight-mvc-php-framework-3po0</link>
      <guid>https://dev.to/ravikishan/introducing-nexaphp-a-lightweight-mvc-php-framework-3po0</guid>
      <description>&lt;p&gt;Building PHP applications often involves a lot of boilerplate code and organization to maintain a clean structure. Many developers reach for frameworks like Laravel or Symfony to handle this, but what if you just need a light, straightforward MVC (Model-View-Controller) framework? &lt;strong&gt;NexaPHP&lt;/strong&gt; might be exactly what you're looking for. This minimalist framework is designed for developers who want a lean structure without all the weight of larger frameworks, making it an ideal choice for learning or creating small to medium-sized applications.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why NexaPHP?
&lt;/h3&gt;

&lt;p&gt;NexaPHP is tailored for developers who value simplicity and want more control over the core framework functionality. The design of NexaPHP is straightforward and lets you focus on essential aspects of your application without navigating through heavy framework abstractions. Here’s what NexaPHP offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight and minimal&lt;/strong&gt; - Core MVC components without excessive dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy setup and configuration&lt;/strong&gt; - Straightforward configuration for database and routing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middleware support&lt;/strong&gt; - Add custom middleware for enhanced request filtering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event-driven&lt;/strong&gt; - Use custom events to customize application behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you're a beginner or an experienced developer wanting to learn MVC principles, NexaPHP’s small footprint allows you to dive directly into PHP web development. &lt;/p&gt;




&lt;h3&gt;
  
  
  Getting Started with NexaPHP
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Installation
&lt;/h4&gt;

&lt;p&gt;Install NexaPHP via Composer, which makes it easy to integrate into any PHP project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require ravikisha/nexaphp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Basic Setup
&lt;/h4&gt;

&lt;p&gt;To initialize a NexaPHP application, configure your application root directory and database details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;ravikisha\nexaphp\Application&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'userClass'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;\app\models\User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'db'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'dsn'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'mysql:host=localhost;dbname=testdb'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'root'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;userClass&lt;/strong&gt;: Defines the User model, critical for handling user authentication and management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;db&lt;/strong&gt;: Provides database connection parameters, including Data Source Name (DSN), user, and password.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Key Components in NexaPHP
&lt;/h3&gt;

&lt;p&gt;NexaPHP provides several foundational classes that power its core MVC structure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Application&lt;/strong&gt;: Manages the lifecycle of your app and orchestrates different components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Router&lt;/strong&gt;: Maps URLs to specific controllers and actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request&lt;/strong&gt; and &lt;strong&gt;Response&lt;/strong&gt;: Handle HTTP requests and responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt;: Manages database connections and queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session&lt;/strong&gt;: Offers session management functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View&lt;/strong&gt;: Handles the rendering of HTML templates.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Building Your First Controller
&lt;/h3&gt;

&lt;p&gt;Controllers define how NexaPHP handles requests for different routes. Here’s an example of a &lt;code&gt;SiteController&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;app\controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;ravikisha\nexaphp\Controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SiteController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;home&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'home'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;contact&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="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'contact'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;$this-&amp;gt;render()&lt;/code&gt; renders a view file, while &lt;code&gt;setLayout()&lt;/code&gt; can define custom layouts.&lt;/p&gt;




&lt;h3&gt;
  
  
  Defining Routes
&lt;/h3&gt;

&lt;p&gt;The Router allows you to define GET and POST routes that correspond to specific controller actions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;SiteController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'home'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/contact'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;SiteController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'contact'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NexaPHP supports dynamic routes with parameters, allowing you to handle user-specific pages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/profile/{id}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;UserController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'profile'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Database Integration
&lt;/h3&gt;

&lt;p&gt;NexaPHP uses PDO for database interactions, making it easy to integrate with various databases. Here’s a quick overview:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Defining a Model&lt;/strong&gt;: Use models to interact with database tables.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;app\models&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;ravikisha\nexaphp\db\DBModel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;DBModel&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&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="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Migrations&lt;/strong&gt;: NexaPHP can run migrations to keep the database schema updated:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;applyMigrations&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CRUD Operations&lt;/strong&gt;: NexaPHP provides methods like &lt;code&gt;save()&lt;/code&gt; and &lt;code&gt;findOne()&lt;/code&gt; for database operations.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Middleware Support
&lt;/h3&gt;

&lt;p&gt;NexaPHP’s middleware feature allows you to implement request filtering and control. Here’s an example of creating and applying custom middleware:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;app\middlewares&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;ravikisha\nexaphp\middlewares\BaseMiddleware&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthMiddleware&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseMiddleware&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Authentication logic&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;To register middleware:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;registerMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthMiddleware&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'profile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'settings'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Views and Templating
&lt;/h3&gt;

&lt;p&gt;NexaPHP views offer a simple way to manage HTML templates. By default, templates are stored in the &lt;code&gt;views&lt;/code&gt; folder, and you can use layout files to maintain a consistent design.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'profile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Layouts can be defined under &lt;code&gt;views/layouts&lt;/code&gt;, and placeholders like &lt;code&gt;{{content}}&lt;/code&gt; allow views to be inserted dynamically.&lt;/p&gt;




&lt;h3&gt;
  
  
  Forms and Fields
&lt;/h3&gt;

&lt;p&gt;NexaPHP offers a convenient form and field builder, making it easy to create dynamic HTML forms:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;ravikisha\nexaphp\form\Form&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;begin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/submit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'post'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$form&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Form&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can render various field types such as password, email, and date fields for different form requirements.&lt;/p&gt;




&lt;h3&gt;
  
  
  Session Management
&lt;/h3&gt;

&lt;p&gt;The Session class provides session handling, allowing you to set, get, and manage flash messages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setFlash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Logged in successfully'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is particularly useful for displaying temporary notifications.&lt;/p&gt;




&lt;h3&gt;
  
  
  Exception Handling
&lt;/h3&gt;

&lt;p&gt;NexaPHP has built-in support for handling exceptions, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NotFoundException&lt;/strong&gt; for invalid routes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ForbiddenException&lt;/strong&gt; for access control.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  User Authentication
&lt;/h3&gt;

&lt;p&gt;User authentication is managed through the abstract &lt;code&gt;UserModel&lt;/code&gt; class, which provides foundational methods like &lt;code&gt;login()&lt;/code&gt;, &lt;code&gt;logout()&lt;/code&gt;, and &lt;code&gt;isGuest()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UserModel&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getDisplayName&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Sample NexaPHP Application
&lt;/h3&gt;

&lt;p&gt;Below is an example of a basic NexaPHP application setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;ravikisha\nexaphp\Application&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;app\controllers\SiteController&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'userClass'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;\app\models\User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'db'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'dsn'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'mysql:host=localhost;dbname=testdb'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'root'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;SiteController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'home'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/contact'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;SiteController&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'contact'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nv"&gt;$app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;NexaPHP provides a clean and concise way to build MVC applications with PHP. While it’s intended for learning and small projects, it’s a great choice for those who want to understand how an MVC framework works under the hood. Explore the framework on GitHub or install it via Composer to get started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ravikisha/nexaphp" rel="noopener noreferrer"&gt;NexaPHP GitHub&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Composer:&lt;/strong&gt; &lt;a href="https://packagist.org/packages/ravikisha/nexaphp" rel="noopener noreferrer"&gt;NexaPHP on Packagist&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a Regex Engine in Go: Introducing MatchGo</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Mon, 04 Nov 2024 18:09:27 +0000</pubDate>
      <link>https://dev.to/ravikishan/building-a-regex-engine-in-go-introducing-matchgo-4i76</link>
      <guid>https://dev.to/ravikishan/building-a-regex-engine-in-go-introducing-matchgo-4i76</guid>
      <description>&lt;p&gt;In today's programming landscape, regular expressions (regex) are invaluable tools for text processing, enabling developers to search, match, and manipulate strings with precision. I recently embarked on an exciting project to create a regex engine in Go, named &lt;strong&gt;MatchGo&lt;/strong&gt;, utilizing a Non-deterministic Finite Automaton (NFA) approach. This blog post will walk you through the development journey of MatchGo, highlighting its features and practical usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;MatchGo is an experimental regex engine designed for simplicity and ease of use. It allows you to compile regex patterns, check strings for matches, and extract matched groups. While it's still in development, I aimed to create a functional library that adheres to core regex principles, inspired by various resources and regex implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Basic Syntax Support&lt;/strong&gt;: MatchGo supports foundational regex constructs, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Anchors&lt;/strong&gt;: &lt;code&gt;^&lt;/code&gt; (beginning) and &lt;code&gt;$&lt;/code&gt; (end) of strings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wildcards&lt;/strong&gt;: &lt;code&gt;.&lt;/code&gt; to match any single character.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Character Classes&lt;/strong&gt;: Bracket notation &lt;code&gt;[ ]&lt;/code&gt; and negation &lt;code&gt;[^ ]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quantifiers&lt;/strong&gt;: &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, and &lt;code&gt;{m,n}&lt;/code&gt; for specifying repetition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capturing Groups&lt;/strong&gt;: &lt;code&gt;( )&lt;/code&gt; for grouping and backreferences.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Special Character Handling&lt;/strong&gt;: MatchGo supports escape sequences and manages special characters in regex, ensuring accurate parsing and matching.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiline Support&lt;/strong&gt;: The engine has been tested with multiline inputs, where &lt;code&gt;.&lt;/code&gt; does not match newlines (&lt;code&gt;\n&lt;/code&gt;), and &lt;code&gt;$&lt;/code&gt; correctly matches the end of lines.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;: Improved error handling mechanisms to provide clear feedback during compilation and matching.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;To incorporate MatchGo into your Go project, simply run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get github.com/Ravikisha/matchgo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Getting started with MatchGo is straightforward. Here’s how you can compile a regex pattern and test it against a string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"github.com/Ravikisha/matchgo"&lt;/span&gt;

&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;matchgo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"your-regex-pattern"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// handle error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"your-string"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Matches&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Access matched groups by name&lt;/span&gt;
    &lt;span class="n"&gt;groupMatchString&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Groups&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"group-name"&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;To find all matches in a string, use &lt;code&gt;FindMatches&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindMatches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"your-string"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Process each match&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Matches&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Match found:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Groups&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example Code
&lt;/h3&gt;

&lt;p&gt;Here’s a practical example demonstrating how to use MatchGo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/Ravikisha/matchgo"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;matchgo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"([a-z]+) ([0-9]+)"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error compiling pattern:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&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="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello 123"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Matches&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Match found:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Groups&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Match found: map[0:hello 123 1:hello 2:123]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Development Insights
&lt;/h2&gt;

&lt;p&gt;Developing MatchGo involved significant research and implementation of various regex principles. Here are some of the critical aspects of the engine:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NFA Implementation&lt;/strong&gt;: The engine builds a non-deterministic finite automaton (NFA) from the regex patterns, enabling efficient matching.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token Parsing&lt;/strong&gt;: MatchGo parses the regex string into tokens, allowing for flexible matching strategies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Management&lt;/strong&gt;: The engine maintains states for capturing groups and backreferences, enhancing its ability to handle complex regex patterns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Extensibility&lt;/strong&gt;: Although currently minimalistic, the engine is designed with extensibility in mind, allowing for future enhancements and additional features.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fxsh0f3lvz05mn0nrzcfj.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%2Fxsh0f3lvz05mn0nrzcfj.png" alt="Diagram MatchGo" width="367" height="1101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources and References
&lt;/h2&gt;

&lt;p&gt;Throughout the development of MatchGo, I referred to various resources, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://deniskyashif.com/2019/02/17/implementing-a-regular-expression-engine/" rel="noopener noreferrer"&gt;Implementing a Regex Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Thompson%27s_construction" rel="noopener noreferrer"&gt;Thompson’s Construction - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gobyexample.com/" rel="noopener noreferrer"&gt;Go by Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://regex101.com/" rel="noopener noreferrer"&gt;Regex101&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These resources provided invaluable insights and helped refine the implementation.&lt;/p&gt;

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

&lt;p&gt;MatchGo is an exciting step into the world of regex engines, offering a simple yet functional tool for developers looking to integrate regex capabilities into their Go applications. As this project evolves, I look forward to enhancing its features and refining its performance.&lt;/p&gt;

&lt;p&gt;Feel free to check out the &lt;a href="https://github.com/Ravikisha/matchgo" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; for more information, contribute, or experiment with the engine in your own projects. Happy coding!&lt;/p&gt;

</description>
      <category>go</category>
      <category>regex</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a URL Shortener with Rate Limiting and Redis in Go</title>
      <dc:creator>Ravi Kishan</dc:creator>
      <pubDate>Mon, 04 Nov 2024 14:33:20 +0000</pubDate>
      <link>https://dev.to/ravikishan/building-a-url-shortener-with-rate-limiting-and-redis-in-go-5ab</link>
      <guid>https://dev.to/ravikishan/building-a-url-shortener-with-rate-limiting-and-redis-in-go-5ab</guid>
      <description>&lt;p&gt;URL shorteners like Bitly or TinyURL are incredibly popular tools, but have you ever wondered what goes into building one? In this blog, we’ll dive into how I built a custom URL shortener in Go with rate limiting and a Redis database for data storage and IP tracking. We’ll cover the core features, the tech stack, and the challenges I encountered along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;This URL shortener application accepts long URLs from users, generates shorter, unique links, and allows users to customize the shortened alias if desired. The server redirects any visitor who uses the shortened URL to the original long URL.&lt;/p&gt;

&lt;p&gt;Here's a quick overview of the primary components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WebServer&lt;/strong&gt;: Handles routing and requests using the Fiber framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limiter&lt;/strong&gt;: Manages user requests to prevent abuse, limiting the number of requests an IP can make in a given timeframe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL Validator&lt;/strong&gt;: Ensures URLs are in a valid format and ready for storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL Generator&lt;/strong&gt;: Generates unique short links for each long URL or uses custom aliases provided by users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis Database&lt;/strong&gt;: Stores URL mappings and IP rate limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these features in mind, let’s break down the implementation.&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%2Fexkfi2fmsdethbdbz3gz.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%2Fexkfi2fmsdethbdbz3gz.png" alt="Diagram Url Shortener" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt;: Fast and efficient, Go is ideal for building a high-performance URL shortener.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fiber&lt;/strong&gt;: A web framework in Go, chosen for its lightweight performance and simplicity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis&lt;/strong&gt;: An in-memory database used to store URL mappings and IP quotas, giving us speed and persistence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: Containers make setting up Redis easy and ensure the application is portable and scalable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;The core files and folders are organized as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── main.go               # Entry point for the application
├── routes/
│   ├── shorten.go        # Handles URL shortening and redirects
├── database/
│   ├── redis.go          # Database connection logic
├── helpers/
│   ├── helper.go         # Utility functions for URL validation
├── .env                  # Environment variables
├── docker-compose.yml    # Docker setup for Redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setting Up the Application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Main Server Logic (&lt;code&gt;main.go&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Our main application file sets up the routes for shortening and resolving URLs. Here’s the code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/gofiber/fiber/v2"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gofiber/fiber/v2/middleware/logger"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/joho/godotenv"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/ravikisha/url-shortener/routes"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;setupRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fiber&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/:url"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResolveURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShortenURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;godotenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error loading .env file"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fiber&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="n"&gt;setupRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"APP_PORT"&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;
  
  
  2. Rate Limiting and URL Shortening (&lt;code&gt;shorten.go&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;To prevent abuse, we use Redis to keep track of each IP address and limit the number of allowed requests. Here’s the flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Check Rate Limits&lt;/strong&gt;: When a request is made, the rate limiter checks Redis to see how many requests the IP has made.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process URL&lt;/strong&gt;: If the rate limit is not exceeded, the server validates the URL and shortens it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate or Use Alias&lt;/strong&gt;: If the user provides a custom alias, we store it. Otherwise, we generate a unique ID.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;routes&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/asaskevich/govalidator"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/go-redis/redis/v8"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gofiber/fiber/v2"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/ravikisha/url-shortener/database"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/ravikisha/url-shortener/helpers"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Define structs for the request and response data&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;URL&lt;/span&gt;         &lt;span class="kt"&gt;string&lt;/span&gt;        &lt;span class="s"&gt;`json:"url"`&lt;/span&gt;
    &lt;span class="n"&gt;CustomShort&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;        &lt;span class="s"&gt;`json:"short"`&lt;/span&gt;
    &lt;span class="n"&gt;Expiry&lt;/span&gt;      &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="s"&gt;`json:"expiry"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;URL&lt;/span&gt;             &lt;span class="kt"&gt;string&lt;/span&gt;        &lt;span class="s"&gt;`json:"url"`&lt;/span&gt;
    &lt;span class="n"&gt;CustomShort&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;        &lt;span class="s"&gt;`json:"short"`&lt;/span&gt;
    &lt;span class="n"&gt;Expiry&lt;/span&gt;          &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="s"&gt;`json:"expiry"`&lt;/span&gt;
    &lt;span class="n"&gt;XRateRemaining&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;           &lt;span class="s"&gt;`json:"x-rate-remaining"`&lt;/span&gt;
    &lt;span class="n"&gt;XRateLimitReset&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="s"&gt;`json:"x-rate-limit-reset"`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Redis Database Setup (&lt;code&gt;redis.go&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;redis.go&lt;/code&gt;, we define a helper function to connect to Redis. This connection is used across different components to store short URLs and enforce rate limits. Here's a simple example of how Redis is configured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"context"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/go-redis/redis/v8"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;Ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dbNum&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;rdb&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Addr&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;"localhost:6379"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Password&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="n"&gt;dbNum&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="n"&gt;rdb&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Docker Setup
&lt;/h2&gt;

&lt;p&gt;To simplify setting up Redis, I used Docker. This makes the application portable and easy to deploy.&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;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;3'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redis:alpine"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6379:6379"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the Application
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repository from GitHub: &lt;a href="https://github.com/Ravikisha/URLShortener" rel="noopener noreferrer"&gt;URLShortener&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the Docker container for Redis:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set environment variables in &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_ADDR="localhost:6379"
DB_PASSWORD=""
APP_PORT=":6767"
DOMAIN="localhost:6767"
APP_QUOTA=10
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the Go application:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, the application is live, and you can start shortening URLs!&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the URL Shortener
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Shortening a URL
&lt;/h3&gt;

&lt;p&gt;Send a POST request to &lt;code&gt;/api/v1&lt;/code&gt; with the following JSON payload:&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;"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://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"short"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"exmpl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"expiry"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&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;h3&gt;
  
  
  Accessing a Shortened URL
&lt;/h3&gt;

&lt;p&gt;Use the generated short URL, like &lt;code&gt;http://localhost:6767/exmpl&lt;/code&gt;, to be redirected to &lt;code&gt;https://example.com&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Learnings
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Using Redis for Rate Limiting&lt;/strong&gt;: Redis is incredibly fast, and using it for both URL storage and rate limiting was efficient and effective.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building a REST API with Fiber&lt;/strong&gt;: Fiber's simplicity and performance are well-suited for building APIs in Go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling and Validation&lt;/strong&gt;: Ensuring robust error handling and URL validation was essential to providing a user-friendly experience.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Future Improvements
&lt;/h2&gt;

&lt;p&gt;There are a few features and optimizations I’d like to add in the future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Admin Dashboard&lt;/strong&gt;: A UI to track URL usage and monitor statistics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detailed Analytics&lt;/strong&gt;: Track click counts, referrers, and user demographics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Deploy the app on a cloud provider and use distributed Redis for handling more extensive data.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Building this URL shortener was a rewarding experience and a great way to explore Go, Fiber, and Redis. This project provides a solid foundation, whether you're learning about backend development or exploring Go’s potential in web services. &lt;/p&gt;

&lt;p&gt;If you'd like to see the code in action, check out the &lt;a href="https://github.com/Ravikisha/URLShortener" rel="noopener noreferrer"&gt;GitHub repository here&lt;/a&gt;. Let me know your thoughts or if you have suggestions for improving the project!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>go</category>
      <category>redis</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
