<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://madrus.dev/blog</id>
    <title>Madrus's Webdings Blog</title>
    <updated>2025-06-16T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://madrus.dev/blog"/>
    <subtitle>Madrus's Webdings Blog</subtitle>
    <icon>https://madrus.dev/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[Implementing Right-to-Left (RTL) Support in a Tailwind CSS React Application]]></title>
        <id>https://madrus.dev/blog/rtl-implementation-guide</id>
        <link href="https://madrus.dev/blog/rtl-implementation-guide"/>
        <updated>2025-06-16T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[TL;DR I was developing a project for my friends when we started discussing which languages to support. "It would really be great if we had Arabic!" they said. That's when I realized I'd never dealt with Right-to-Left (RTL) languages before - and honestly, it felt a bit intimidating at first. But hey, we love a good challenge, right?]]></summary>
        <content type="html"><![CDATA[<p><strong>TL;DR</strong> I was developing a project for my friends when we started discussing which languages to support. "It would really be great if we had Arabic!" they said. That's when I realized I'd never dealt with Right-to-Left (RTL) languages before - and honestly, it felt a bit intimidating at first. But hey, we love a good challenge, right?</p>
<p>Building a web application with RTL support requires more than just translating labels and text - it requires adapting the entire user interface to be able to swap text directions. This article describes the key changes I made to seamlessly supports both LTR and RTL language like Arabic. Spoiler alert: it's actually quite doable with Tailwind CSS!</p>
<!-- -->
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="understanding-the-challenge">Understanding the Challenge<a href="https://madrus.dev/blog/rtl-implementation-guide#understanding-the-challenge" class="hash-link" aria-label="Direct link to Understanding the Challenge" title="Direct link to Understanding the Challenge">​</a></h2>
<p>When adding RTL support to an existing LTR application, we need to consider:</p>
<ul>
<li><strong>Text direction</strong>: Content flows from right to left</li>
<li><strong>Layout mirroring</strong>: UI elements should mirror horizontally, including paddings, margins, and positioning (left/right properties need to swap)</li>
<li><strong>Icon placement</strong>: Icons and interactive elements should also be repositioned inside their containers</li>
<li><strong>Typography</strong>: Different fonts and sizing may be needed for optimal readability</li>
<li><strong>Form inputs</strong>: Input fields and labels need proper alignment</li>
</ul>
<p>Compare the following two screenshots:</p>
<div style="display:flex;gap:20px;justify-content:center;align-items:flex-start;margin-bottom:20px"><div style="flex:1;text-align:center"><img src="https://madrus.dev/img/01_ltr_layout.png" alt="LTR layout" style="max-height:400px;width:auto;border-radius:8px;box-shadow:0 4px 8px rgba(0,0,0,0.1)"><p style="margin-top:8px;font-size:14px;color:#666">LTR Layout</p></div><div style="flex:1;text-align:center"><img src="https://madrus.dev/img/01_rtl_layout.png" alt="RTL layout" style="max-height:400px;width:auto;border-radius:8px;box-shadow:0 4px 8px rgba(0,0,0,0.1)"><p style="margin-top:8px;font-size:14px;color:#666">RTL Layout</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="setting-up-the-foundation">Setting Up the Foundation<a href="https://madrus.dev/blog/rtl-implementation-guide#setting-up-the-foundation" class="hash-link" aria-label="Direct link to Setting Up the Foundation" title="Direct link to Setting Up the Foundation">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="1-rtl-utility-functions">1. RTL Utility Functions<a href="https://madrus.dev/blog/rtl-implementation-guide#1-rtl-utility-functions" class="hash-link" aria-label="Direct link to 1. RTL Utility Functions" title="Direct link to 1. RTL Utility Functions">​</a></h3>
<p>The first step is creating utility functions to detect RTL languages and provide direction-aware helpers:</p>
<div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/utils/rtlUtils.ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> isRTL </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">boolean</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">'ar'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">includes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> getDirection </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'ltr'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">|</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'rtl'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">isRTL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'rtl'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'ltr'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> getTypographyClass </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">isRTL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'text-arabic'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">''</span><br></span></code></pre></div></div>
<p><strong>Key Benefits:</strong></p>
<ul>
<li>Centralized language detection</li>
<li>Type-safe direction handling</li>
<li>Easy to extend for additional RTL languages</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="html-direction-attribute">HTML Direction Attribute<a href="https://madrus.dev/blog/rtl-implementation-guide#html-direction-attribute" class="hash-link" aria-label="Direct link to HTML Direction Attribute" title="Direct link to HTML Direction Attribute">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="2-setting-the-dir-attribute-on-the-html-tag">2. Setting the <code>dir</code> Attribute on the HTML Tag<a href="https://madrus.dev/blog/rtl-implementation-guide#2-setting-the-dir-attribute-on-the-html-tag" class="hash-link" aria-label="Direct link to 2-setting-the-dir-attribute-on-the-html-tag" title="Direct link to 2-setting-the-dir-attribute-on-the-html-tag">​</a></h3>
<p>The <code>dir</code> attribute must be set on the root HTML element to enable browser-level RTL support. This is the foundation of everything else. When you set <code>dir="rtl"</code> on the <code>&lt;html&gt;</code> tag, the browser automatically:</p>
<ul>
<li>Changes the default text direction from left-to-right to right-to-left</li>
<li>Flips the document flow (scrollbars appear on the left side)</li>
<li>Enables CSS logical properties to work correctly</li>
<li>Provides the proper context for screen readers and accessibility tools</li>
</ul>
<p>Without this attribute, your CSS changes alone won't create a proper RTL experience. So, we can add it like this (e.g. in Remix or React Router 7 project):</p>
<div class="language-tsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-tsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/root.tsx</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">html</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    lang</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">language</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain">   dir</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token function" style="color:rgb(130, 170, 255)">getDirection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">language</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'h-full overflow-x-hidden'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">head</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text">...</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">head</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">body</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text">...</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">body</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">html</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="3-dynamic-direction-updates">3. Dynamic Direction Updates<a href="https://madrus.dev/blog/rtl-implementation-guide#3-dynamic-direction-updates" class="hash-link" aria-label="Direct link to 3. Dynamic Direction Updates" title="Direct link to 3. Dynamic Direction Updates">​</a></h3>
<p>For single-page applications, the direction needs to update when the user switches languages. We can control that dynamically with <code>direction</code> attribute and <code>typographyClass</code> helper:</p>
<details class="details_paXp alert alert--info details_VmOF" data-collapsed="true"><summary>Click to see the full implementation code</summary><div><div class="collapsibleContent_J9cb"><div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/root.tsx - Declarative approach (recommended)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> getDirection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> getTypographyClass </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'~/utils/rtlUtils'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">DocumentProps</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  children</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> React</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">ReactNode</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  language</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(130, 170, 255)">Document</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> children</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> language </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> DocumentProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> i18n </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useTranslation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Use the current language from i18n instance, falling back to initial language</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> currentLanguage </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> i18n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">language </span><span class="token operator" style="color:rgb(137, 221, 255)">||</span><span class="token plain"> language</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Use useState for reactive values that depend on language</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">direction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> setDirection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">getDirection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">currentLanguage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">typographyClass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> setTypographyClass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useState</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">getTypographyClass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">currentLanguage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Update direction, typography, and cookie when language changes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">useEffect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">setDirection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">getDirection</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">currentLanguage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token function" style="color:rgb(130, 170, 255)">setTypographyClass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token function" style="color:rgb(130, 170, 255)">getTypographyClass</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">currentLanguage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">currentLanguage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> i18n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">language</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">html lang</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">currentLanguage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> dir</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">direction</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'h-full overflow-x-hidden'</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">head</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token operator" style="color:rgb(137, 221, 255)">...</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">head</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">body</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token function" style="color:rgb(130, 170, 255)">cn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token string" style="color:rgb(195, 232, 141)">'bg-background text-foreground flex h-full flex-col'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          typographyClass</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">children</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">body</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">html</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div></div></div></details>
<p><img decoding="async" loading="lazy" alt="dir=rtl on html tag" src="https://madrus.dev/assets/images/dir=rtl_example-b43bd7defd94744b16e99ce1f821094d.png" width="866" height="103" class="img_y867"></p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="tailwind-css-logical-properties">Tailwind CSS Logical Properties<a href="https://madrus.dev/blog/rtl-implementation-guide#tailwind-css-logical-properties" class="hash-link" aria-label="Direct link to Tailwind CSS Logical Properties" title="Direct link to Tailwind CSS Logical Properties">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="4-replacing-physical-properties-with-logical-properties">4. Replacing Physical Properties with Logical Properties<a href="https://madrus.dev/blog/rtl-implementation-guide#4-replacing-physical-properties-with-logical-properties" class="hash-link" aria-label="Direct link to 4. Replacing Physical Properties with Logical Properties" title="Direct link to 4. Replacing Physical Properties with Logical Properties">​</a></h3>
<p>The most significant change is moving from physical properties (left/right) to logical properties (start/end):</p>
<p><strong>Before (Physical Properties):</strong></p>
<div class="language-css codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-css codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ❌ Physical properties - don't adapt to text direction */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.ml-4     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-left */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-left */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-left */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-left */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.mr-2     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-right */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.pl-3     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* padding-left */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.pr-6     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* padding-right */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.text-left</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></span></code></pre></div></div>
<p><strong>After (Logical Properties):</strong></p>
<div class="language-css codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-css codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* ✅ Logical properties - automatically adapt to text direction */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.ms-4     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-inline-start */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-inline-start */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-inline-start */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-inline-start */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.me-2     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* margin-inline-end */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.ps-3     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* padding-inline-start */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.pe-6     </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* padding-inline-end */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">.text-start</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></span></code></pre></div></div>
<div class="theme-admonition theme-admonition-info admonition_nV6I alert alert--info"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>More Information</div><div class="admonitionContent_vlwu"><p>Read more on using logical properties in the <a href="https://tailwindcss.com/docs/top-right-bottom-left#using-logical-properties" target="_blank" rel="noopener noreferrer">Tailwind documentation</a>.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="component-adaptations">Component Adaptations<a href="https://madrus.dev/blog/rtl-implementation-guide#component-adaptations" class="hash-link" aria-label="Direct link to Component Adaptations" title="Direct link to Component Adaptations">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="5-form-input-components">5. Form Input Components<a href="https://madrus.dev/blog/rtl-implementation-guide#5-form-input-components" class="hash-link" aria-label="Direct link to 5. Form Input Components" title="Direct link to 5. Form Input Components">​</a></h3>
<p>Form components like combos having a chevron icon on the right to open it when in LTR, also need to be edited for proper RTL layout with the icon on the left:</p>
<div class="language-tsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-tsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/components/inputs/ComboField.tsx</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">select</span><span class="token tag" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag" style="color:rgb(255, 85, 114)">  </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">className</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript function" style="color:rgb(130, 170, 255)">cn</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><span class="token tag script language-javascript operator" style="color:rgb(137, 221, 255)">-</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">   </span><span class="token tag script language-javascript string" style="color:rgb(195, 232, 141)">'h-12 w-full border-2 border-emerald-700/30 bg-white px-0 pl-3 pr-6 text-lg leading-6'</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><span class="token tag script language-javascript operator" style="color:rgb(137, 221, 255)">+</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">   </span><span class="token tag script language-javascript string" style="color:rgb(195, 232, 141)">'h-12 w-full border-2 border-emerald-700/30 bg-white px-0 ps-3 pe-6 text-lg leading-6'</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">  </span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag" style="color:rgb(255, 85, 114)"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* options */</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">select</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">span</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line theme-code-block-highlighted-line" style="color:#bfc7d5"><span class="token plain-text">+ </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">span</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">pointer-events-none absolute inset-y-0 end-0 flex items-center pe-2</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="6-button-components-with-icons">6. Button Components with Icons<a href="https://madrus.dev/blog/rtl-implementation-guide#6-button-components-with-icons" class="hash-link" aria-label="Direct link to 6. Button Components with Icons" title="Direct link to 6. Button Components with Icons">​</a></h3>
<p>Buttons with icons need special handling to maintain proper visual hierarchy. In Latin (LTR) languages, icons typically appear to the left of the label, while in Arabic (RTL), they should appear to the right of the label to maintain natural reading flow (notice <code>flex-row-reverse</code> class in RTL-mode):</p>
<div class="language-ts codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-ts codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/components/buttons/DeleteButton.tsx</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">DeleteButton</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> onClick</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> label </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> DeleteButtonProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">JSX</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Element </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> i18n </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useTranslation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> rtl </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">isRTL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">i18n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">language</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">button</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      type</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'button'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      onClick</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">onClick</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token function" style="color:rgb(130, 170, 255)">cn</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        rtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'flex-row-reverse'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'flex-row'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">'inline-flex items-center justify-center rounded-md border border-red-300'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string" style="color:rgb(195, 232, 141)">'bg-white gap-2 px-3 py-2 text-sm font-medium text-red-700'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">TrashIcon className</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">h-4 w-4 </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token template-string interpolation">rtl </span><span class="token template-string interpolation operator" style="color:rgb(137, 221, 255)">?</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation string" style="color:rgb(195, 232, 141)">''</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation operator" style="color:rgb(137, 221, 255)">:</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation string" style="color:rgb(195, 232, 141)">'mr-2 -ml-1'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">span</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">label</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">span</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">button</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>Compare the following two screenshots:</p>
<p><img decoding="async" loading="lazy" alt="delete button ltr" src="https://madrus.dev/assets/images/02_delete_ltr-0536729dfb18d31dc2fa55f6fd4e0167.png" width="163" height="61" class="img_y867">
<img decoding="async" loading="lazy" alt="delete button ltr" src="https://madrus.dev/assets/images/02_delete_rtl-c31b35974783ff326c4d84f90fdc115c.png" width="137" height="60" class="img_y867"></p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="7-advanced-component-helpers">7. Advanced Component Helpers<a href="https://madrus.dev/blog/rtl-implementation-guide#7-advanced-component-helpers" class="hash-link" aria-label="Direct link to 7. Advanced Component Helpers" title="Direct link to 7. Advanced Component Helpers">​</a></h3>
<p>For more complex components, create reusable helper functions:</p>
<div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/utils/rtlUtils.ts - Advanced helpers</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Chip/Tag component layout helper</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getChipClasses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> container</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">isRTL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// ps-3 = more space where content starts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// pe-2 = less space where delete button is placed</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    container</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'ps-3 pe-2 gap-2 flex-row-reverse'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'ps-3 pe-2 gap-2 flex-row'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Dropdown menu widget positioning helper</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getDropdownProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">isRTL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    align</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'end'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'start'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    side</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'bottom'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    sideOffset</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    alignOffset</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">8</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token number" style="color:rgb(247, 140, 108)">8</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="typography-considerations">Typography Considerations<a href="https://madrus.dev/blog/rtl-implementation-guide#typography-considerations" class="hash-link" aria-label="Direct link to Typography Considerations" title="Direct link to Typography Considerations">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="8-custom-css-for-arabic-typography-and-mixed-content">8. Custom CSS for Arabic Typography and Mixed Content<a href="https://madrus.dev/blog/rtl-implementation-guide#8-custom-css-for-arabic-typography-and-mixed-content" class="hash-link" aria-label="Direct link to 8. Custom CSS for Arabic Typography and Mixed Content" title="Direct link to 8. Custom CSS for Arabic Typography and Mixed Content">​</a></h3>
<p>Arabic text may require special typography treatment for optimal readability, especially when mixed with Latin text. Arabic letters appear much smaller and thinner than Latin letters at the same font size within the same font family, so we can increase the Arabic font size by 20-25% to achieve visual balance:</p>
<div class="language-css codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-css codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* app/styles/tailwind.css */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Script-aware typography system */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Global Arabic sizing - applied to body when app language is Arabic */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token selector class" style="color:rgb(199, 146, 234)">.text-arabic</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">font-size</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1.2</span><span class="token unit">em</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Make text 20% larger for Arabic readability */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Latin text - use rem to bypass inherited em scaling from body */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token selector class" style="color:rgb(199, 146, 234)">.text-latin</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">font-size</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0.875</span><span class="token unit">em</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Make text 20$ smaller if mixing latin in rtl */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* Form inputs in RTL */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token selector attribute punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token selector attribute attr-name" style="color:rgb(255, 203, 107)">dir</span><span class="token selector attribute operator" style="color:rgb(137, 221, 255)">=</span><span class="token selector attribute attr-value" style="color:rgb(199, 146, 234)">'rtl'</span><span class="token selector attribute punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token selector" style="color:rgb(199, 146, 234)"> input</span><span class="token selector punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token selector" style="color:rgb(199, 146, 234)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token selector" style="color:rgb(199, 146, 234)"></span><span class="token selector attribute punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token selector attribute attr-name" style="color:rgb(255, 203, 107)">dir</span><span class="token selector attribute operator" style="color:rgb(137, 221, 255)">=</span><span class="token selector attribute attr-value" style="color:rgb(199, 146, 234)">'rtl'</span><span class="token selector attribute punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token selector" style="color:rgb(199, 146, 234)"> textarea</span><span class="token selector punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token selector" style="color:rgb(199, 146, 234)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token selector" style="color:rgb(199, 146, 234)"></span><span class="token selector attribute punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token selector attribute attr-name" style="color:rgb(255, 203, 107)">dir</span><span class="token selector attribute operator" style="color:rgb(137, 221, 255)">=</span><span class="token selector attribute attr-value" style="color:rgb(199, 146, 234)">'rtl'</span><span class="token selector attribute punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token selector" style="color:rgb(199, 146, 234)"> select</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">text-align</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> right</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="practical-examples-of-mixed-content">Practical Examples of Mixed Content<a href="https://madrus.dev/blog/rtl-implementation-guide#practical-examples-of-mixed-content" class="hash-link" aria-label="Direct link to Practical Examples of Mixed Content" title="Direct link to Practical Examples of Mixed Content">​</a></h4>
<p><strong>Example 1: Arabic Text Within English Documentation</strong></p>
<p>When we have Arabic text within a primarily English interface, we need to ensure proper font sizing:</p>
<div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Help documentation or user instructions with Arabic phrases</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">div className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'documentation-section'</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">p</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    To create a tournament </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> Arabic</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> the </span><span class="token keyword" style="font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">will</span><span class="token plain"> display</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token string" style="color:rgb(195, 232, 141)">' '</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">span className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'text-arabic'</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">إنشاء بطولة </span><span class="token generic-function function" style="color:rgb(130, 170, 255)">جديدة</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">/</span><span class="token generic-function generic class-name" style="color:rgb(255, 203, 107)">span</span><span class="token generic-function generic class-name operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">Create New Tournament</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"> The</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    Arabic text maintains proper readability</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">p</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">div</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><br></span></code></pre></div></div>
<p><strong>Example 2: Technical Terms in Arabic Interface</strong></p>
<p>When the interface is in Arabic but contains technical terms or app names:</p>
<div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Arabic interface with Latin technical terms</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">div className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'notification bg-blue-50 p-4'</span><span class="token plain"> dir</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'rtl'</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">p className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'text-arabic'</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    تم حفظ الفريق بنجاح في قاعدة البيانات</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"> يمكنك الآن الوصول إليه عبر</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">span className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'text-latin'</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain">MyApp </span><span class="token constant" style="color:rgb(130, 170, 255)">API</span><span class="token plain"> v2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">span</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    أو من خلال لوحة التحكم</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">p</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/*</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">    Translation: "The team was saved successfully to the database.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">    We can now access it via MyApp API v2.1 or through the control panel."</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">  */</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">div</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="9-typography-helper-functions">9. Typography Helper Functions<a href="https://madrus.dev/blog/rtl-implementation-guide#9-typography-helper-functions" class="hash-link" aria-label="Direct link to 9. Typography Helper Functions" title="Direct link to 9. Typography Helper Functions">​</a></h3>
<div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/utils/rtlUtils.ts - Typography helpers</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getTypographyClasses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> TypographyClasses </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">isRTL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    title</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'leading-tight'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'leading-normal'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    heading</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'tracking-normal'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'tracking-tight'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    textAlign</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'text-right'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'text-left'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    mixedContent</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'leading-snug text-center'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'leading-normal text-center'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>Compare the following two screenshots:</p>
<p><img decoding="async" loading="lazy" alt="arabic font wihout size fix" src="https://madrus.dev/assets/images/03_no_size_fix-3879e003f69b05a7b1e17a02cc7f3173.png" width="137" height="65" class="img_y867">
<img decoding="async" loading="lazy" alt="arabic font with size fix" src="https://madrus.dev/assets/images/03_with_size_fix-351739d1af153334dd33697f7a64a99a.png" width="137" height="65" class="img_y867"></p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="advanced-layout-patterns">Advanced Layout Patterns<a href="https://madrus.dev/blog/rtl-implementation-guide#advanced-layout-patterns" class="hash-link" aria-label="Direct link to Advanced Layout Patterns" title="Direct link to Advanced Layout Patterns">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="10-react-hook-for-rtl-support">10. React Hook for RTL Support<a href="https://madrus.dev/blog/rtl-implementation-guide#10-react-hook-for-rtl-support" class="hash-link" aria-label="Direct link to 10. React Hook for RTL Support" title="Direct link to 10. React Hook for RTL Support">​</a></h3>
<p>We can create a custom hook to simplify RTL logic in components:</p>
<details class="details_paXp alert alert--info details_VmOF" data-collapsed="true"><summary>Click to see the full implementation code</summary><div><div class="collapsibleContent_J9cb"><div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/utils/rtlUtils.ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Helper for manual dropdown positioning with proper spacing</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getMenuClasses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> MenuClasses </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">isRTL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">languageCode</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Use logical properties for spacing</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    spacing</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'me-4'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'ms-4'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// margin-inline-end : margin-inline-start</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    alignment</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'end-0'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'start-0'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// inset-inline-end : inset-inline-start</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Menu item layout - icons on correct side for RTL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    menuItem</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'flex flex-row-reverse'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'flex flex-row'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Icon container positioning</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    iconContainer</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'flex w-8 items-center justify-end ps-2 pe-0 text-end'</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Icon on right in RTL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'flex w-8 items-center justify-start ps-0 pe-2 text-start'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Icon on left in LTR</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Text container alignment</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    textContainer</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> isRtl </span><span class="token operator" style="color:rgb(137, 221, 255)">?</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'text-right'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'text-left'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/hooks/useRTLDropdown.ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useRTLDropdown</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  dropdownProps</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> DropdownProps</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  menuClasses</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> MenuClasses</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  isRTL</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">boolean</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> i18n </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useTranslation</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    dropdownProps</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getDropdownProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">i18n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">language</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    menuClasses</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">getMenuClasses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">i18n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">language</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    isRTL</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">isRTL</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">i18n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">language</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div></div></div></details>
<p>And then somewhere in a component:</p>
<div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">MyDropdown</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> dropdownProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> menuClasses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> isRTL </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useRTLDropdown</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">DropdownMenu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Content </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain">dropdownProps</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">div className</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">menuClasses</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">spacing</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/* content */</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">div</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">DropdownMenu</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">Content</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="testing-and-validation">Testing and Validation<a href="https://madrus.dev/blog/rtl-implementation-guide#testing-and-validation" class="hash-link" aria-label="Direct link to Testing and Validation" title="Direct link to Testing and Validation">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="11-testing-strategy">11. Testing Strategy<a href="https://madrus.dev/blog/rtl-implementation-guide#11-testing-strategy" class="hash-link" aria-label="Direct link to 11. Testing Strategy" title="Direct link to 11. Testing Strategy">​</a></h3>
<p>We can test our RTL-setup by checking the presence of specific classes like <code>flex-row-reverse</code> when in Arabic:</p>
<div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// app/components/buttons/__tests__/DeleteButton.test.tsx</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> render</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> screen </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@testing-library/react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> I18nextProvider </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'react-i18next'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> initI18n </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'~/i18n/config'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">test</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'renders with proper RTL classes in Arabic'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> i18n </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">initI18n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'ar'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">render</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">I18nextProvider i18n</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">i18n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">DeleteButton onClick</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> label</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">'Delete'</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">I18nextProvider</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> button </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> screen</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">getByRole</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'button'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// Check that the button has flex-row-reverse for RTL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">expect</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">button</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">className</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">toMatch</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex">flex-row-reverse</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="12-visual-testing-checklist">12. Visual Testing Checklist<a href="https://madrus.dev/blog/rtl-implementation-guide#12-visual-testing-checklist" class="hash-link" aria-label="Direct link to 12. Visual Testing Checklist" title="Direct link to 12. Visual Testing Checklist">​</a></h3>
<p>No matter how well we set up our RTL implementation and test it with unit tests, we still need to visually verify that everything looks on the screen the way it should. This can be done manually or automated with end-to-end (e2e) tests. Here's a checklist of things we want to make sure look as expected:</p>
<ul class="contains-task-list containsTaskList_UpU5">
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Text flows in the correct direction</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Icons appear on the correct side</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Form inputs align properly</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Dropdown menus position correctly</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Navigation elements mirror appropriately</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Scrollbars appear on the correct side</li>
<li class="task-list-item"><input type="checkbox" disabled=""> <!-- -->Modal dialogs have elements inside mirror appropriately</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="pitfalls-to-avoid">Pitfalls to Avoid<a href="https://madrus.dev/blog/rtl-implementation-guide#pitfalls-to-avoid" class="hash-link" aria-label="Direct link to Pitfalls to Avoid" title="Direct link to Pitfalls to Avoid">​</a></h2>
<p>To be on the safe side,</p>
<ul>
<li><strong>Don't</strong> mix physical and logical properties in the same component</li>
<li><strong>Don't</strong> forget to update the HTML <code>dir</code> attribute dynamically</li>
<li><strong>Don't</strong> assume all text will automatically align correctly</li>
<li><strong>Don't</strong> hardcode icon positions without considering RTL</li>
<li><strong>Do</strong> test with actual RTL content, not placeholder text</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="conclusion">Conclusion<a href="https://madrus.dev/blog/rtl-implementation-guide#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>Implementing RTL support requires systematic changes across our application, but with Tailwind CSS's logical properties and a well-structured approach, we can create truly bidirectional layouts that feel natural to users regardless of their language preference.</p>
<p>To achieve this we need to:</p>
<ol>
<li>Start with a solid foundation of utility functions</li>
<li>Replace physical properties with logical properties systematically</li>
<li>Handle complex components with conditional logic</li>
<li>Test thoroughly with real content</li>
</ol>
<p>This approach ensures our application provides an excellent user experience for both LTR and RTL language speakers and make our application truly international.</p>
<p>I hope these tips will help you to successfully implement RTL flows in your applications, inshallah!</p>]]></content>
        <author>
            <name>Andre Roussakoff</name>
            <uri>https://github.com/madrus</uri>
        </author>
        <category label="react" term="react"/>
        <category label="tailwind" term="tailwind"/>
        <category label="rtl" term="rtl"/>
        <category label="internationalization" term="internationalization"/>
        <category label="i18n" term="i18n"/>
        <category label="css" term="css"/>
        <category label="typescript" term="typescript"/>
        <category label="remix" term="remix"/>
        <category label="reactrouter" term="reactrouter"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Add Disqus Comments to Docusaurus Blog Posts in 2025]]></title>
        <id>https://madrus.dev/blog/blog-comments-2025</id>
        <link href="https://madrus.dev/blog/blog-comments-2025"/>
        <updated>2025-05-20T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[TL;DR In my previous, now archived, article Add Disqus Comments to Docusaurus Blog Posts (archived) in 2021, I have discussed how to add the Disqus blog comments to a Docusaurus blog. At the time, Docusaurus was in the beta of v2.0.0, React was in v17, and I have used the JavaScript version of swizzling. But the trick I used gained some attention and there were several very inspiring comments, which you can see there. Unfortunately, due to my personal situation I have not acted on them. Until now!]]></summary>
        <content type="html"><![CDATA[<p><strong>TL;DR</strong> In my previous, now archived, article <a href="https://madrus.dev/blog/blog-comments">Add Disqus Comments to Docusaurus Blog Posts (archived)</a> in 2021, I have discussed how to add the Disqus blog comments to a Docusaurus blog. At the time, Docusaurus was in the beta of v2.0.0, React was in v17, and I have used the JavaScript version of swizzling. But the trick I used gained some attention and there were several very inspiring comments, which you can see there. Unfortunately, due to my personal situation I have not acted on them. Until now!</p>
<div class="theme-admonition theme-admonition-important admonition_nV6I alert alert--info"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>UPDATED May 23, 2025</div><div class="admonitionContent_vlwu"><p>In this article you can read how Disqus comments can be added today, in 2025 using the latest and the greatest Docusaurus 3.8.0, React 18 or 19, and TypeScript instead of JavaScript. Of course, if your project needs JavaScript, you can just omit the types.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="lets-go">Let's Go<a href="https://madrus.dev/blog/blog-comments-2025#lets-go" class="hash-link" aria-label="Direct link to Let's Go" title="Direct link to Let's Go">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="prerequisites">Prerequisites<a href="https://madrus.dev/blog/blog-comments-2025#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites">​</a></h3>
<p>Here's what you'll need to get started:</p>
<ol>
<li>your project must be running Docusaurus v3 with at least one blog post;</li>
<li>you have installed your project using <code>theme-classic</code></li>
<li>a terminal session open in the root of your project;</li>
<li>an account with <a href="https://disqus.com/" target="_blank" rel="noopener noreferrer">Disqus</a> with your registered Docusaurus web-app.</li>
</ol>
<p>Install <code>disqus-react</code> and <code>@docusaurus/plugin-content-blog</code>:</p>
<div class="language-bash codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-bash codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">pnpm add disqus-react @docusaurus/plugin-content-blog</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">npm add disqus-react @docusaurus/plugin-content-blog</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">yarn add disqus-react @docusaurus/plugin-content-blog</span><br></span></code></pre></div></div>
<p>If you need some guidance on Disqus weblog registration, see my <a href="https://madrus.dev/blog/register-disqus">Register Your Weblog with Disqus</a> section below.</p>
<hr>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="prepare-the-frontmatter">Prepare the Frontmatter<a href="https://madrus.dev/blog/blog-comments-2025#prepare-the-frontmatter" class="hash-link" aria-label="Direct link to Prepare the Frontmatter" title="Direct link to Prepare the Frontmatter">​</a></h3>
<p>Run your Docusaurus project locally running either <code>yarn start</code> or <code>npm run start</code> in your terminal. Browse to <a href="http://localhost:3000/blog" target="_blank" rel="noopener noreferrer">http://localhost:3000/blog</a> and make sure you see at least one blog post. Choose one of them to work with.</p>
<p>Open the chosen blog post file in your editor of choice and add the following lines in the frontmatter:</p>
<div class="language-yaml codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-yaml codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">slug</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> your</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">blog</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">slug</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">draft</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">comments</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># for Disqus</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">isBlogPostPage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">---</span><br></span></code></pre></div></div>
<ol>
<li>The <code>slug</code> should be unique between different blogposts.</li>
<li>Keep <code>draft</code> value as <code>true</code> until you know for sure everything works fine. What it does is that it lets you see your post while running Docusaurus on localhost but not on the published website. When you are ready, set it to <code>false</code> or remove completely from the frontmatter.</li>
<li>The <code>comments</code> property lets you decide for each blog post if you want your visitors to be able to leave comments. In most cases, you can omit it or set it to <code>true</code>--the comments section will be present by default. Set it to <code>false</code> if you don't want any Disqus comments underneath your blog post.</li>
<li><code>isBlogPostPage</code> is a hack. It is necessary for each blogpost with <code>comments</code> set to <code>true</code>. It seems like a duplication for the <code>comments</code> property but it plays a different role. Without it, the comments are visible and can be placed underneath the short form of the article on the <code>/blog</code> url.</li>
</ol>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="swizzle-the-blogpostitem-component">Swizzle the BlogPostItem component<a href="https://madrus.dev/blog/blog-comments-2025#swizzle-the-blogpostitem-component" class="hash-link" aria-label="Direct link to Swizzle the BlogPostItem component" title="Direct link to Swizzle the BlogPostItem component">​</a></h3>
<p><a href="https://docusaurus.io/docs/swizzling" target="_blank" rel="noopener noreferrer"><strong>Swizzling</strong></a> a Docusaurus component means either adding a wrapper for or including the source code of a core component into your project. This allows us to customize the component's functionality. The application will then use the swizzled and customized version of the component instead of the standard one. In our case, we will be using swizzling to add the Disqus comments on our blog post pages.</p>
<p>Following the tip about adding comments on the Swizzling page, let us wrap the <code>BlogPostItem</code> component. Run the following command and accept the warning about the risks:</p>
<div class="language-bash codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-bash codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">pnpm run swizzle @docusaurus/theme-classic BlogPostItem --danger</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">npm run swizzle @docusaurus/theme-classic BlogPostItem --danger</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">yarn swizzle @docusaurus/theme-classic BlogPostItem --danger</span><br></span></code></pre></div></div>
<p>Choose <code>TypeScript</code> and then <code>Wrap</code>.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="discussionembed">DiscussionEmbed<a href="https://madrus.dev/blog/blog-comments-2025#discussionembed" class="hash-link" aria-label="Direct link to DiscussionEmbed" title="Direct link to DiscussionEmbed">​</a></h3>
<p>Open the <code>index.tsx</code> file inside <code>src/theme/BlogPostItem</code> and let us add our custom code. I have followed the instruction from the <a href="https://github.com/disqus/disqus-react" target="_blank" rel="noopener noreferrer">disqus-react</a> repository. Also, applied the hint of <strong>pjnovas</strong> (a huge round of applause! 👍), which you can find in the discussion hereunder.</p>
<p>Replace the contents of the swizzled <code>src/theme/BlogPostItem/index.tsx</code> with the following code:</p>
<div class="language-tsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_dgyJ">src/theme/BlogPostItem/index.tsx</div><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-tsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> useBlogPost </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@docusaurus/plugin-content-blog/client'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports">useDocusaurusContext</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@docusaurus/useDocusaurusContext'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">BlogPostItem</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@theme-original/BlogPostItem'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token maybe-class-name">Props</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@theme/BlogPostPage'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">DiscussionEmbed</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'disqus-react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">BlogPostItemWrapper</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">props</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Props</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access maybe-class-name">ReactElement</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    metadata</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> frontMatter </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    isBlogPostPage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useBlogPost</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> comments </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> slug</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> title </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> frontMatter</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> identifier </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> slug</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">split</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'-'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">join</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'_'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> siteConfig </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useDocusaurusContext</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> baseUrl </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> siteConfig</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">url</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">+</span><span class="token plain"> siteConfig</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">baseUrl</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> url </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token template-string interpolation">baseUrl</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string string" style="color:rgb(195, 232, 141)">blog</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token template-string interpolation">slug</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag class-name" style="color:rgb(255, 203, 107)">BlogPostItem</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag spread punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token tag spread" style="color:rgb(255, 85, 114)">props</span><span class="token tag spread punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">isBlogPostPage </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> comments </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag class-name" style="color:rgb(255, 203, 107)">DiscussionEmbed</span><span class="token tag" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag" style="color:rgb(255, 85, 114)">          </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">shortname</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">your-short-name</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag" style="color:rgb(255, 85, 114)">          </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">config</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">            identifier</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">            language</span><span class="token tag script language-javascript operator" style="color:rgb(137, 221, 255)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"> </span><span class="token tag script language-javascript string" style="color:rgb(195, 232, 141)">'en_US'</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">            title</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">            url</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">          </span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag" style="color:rgb(255, 85, 114)">        </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>And replace the contents of the <code>index.d.ts</code> file:</p>
<div class="language-tsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_dgyJ">src/theme/BlogPostItem/index.d.ts</div><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-tsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/// &lt;reference types="@docusaurus/plugin-content-blog" /&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">/// &lt;reference types="react" /&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">type</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token maybe-class-name">Props</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@theme/BlogPostPage'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">default</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">BlogPostItemWrapper</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">props</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token maybe-class-name">Props</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access maybe-class-name">ReactElement</span><br></span></code></pre></div></div>
<p>If your web application has been properly registered with Disqus, you should see the Disqus comments appear under every blog post. Once you got it working locally you may set <code>draft: false</code> in the frontmatter or remove the setting completely and publish your project. The comments block will be there as well.</p>
<div class="theme-admonition theme-admonition-caution admonition_nV6I alert alert--warning"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><div class="admonitionContent_vlwu"><p>The comments you add when testing your website locally do not synchronize with the comments of the same deployed page.</p></div></div>
<div class="theme-admonition theme-admonition-danger admonition_nV6I alert alert--danger"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>DO NOT CHANGE YOUR SLUGS</div><div class="admonitionContent_vlwu"><p>Be careful with changing slugs. Your existing comments are connected to it. If you change the slug, you will loose them. If that happens, just restore the old slug.</p></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="commentcount-and-commentembed">CommentCount and CommentEmbed<a href="https://madrus.dev/blog/blog-comments-2025#commentcount-and-commentembed" class="hash-link" aria-label="Direct link to CommentCount and CommentEmbed" title="Direct link to CommentCount and CommentEmbed">​</a></h3>
<p>Using the <code>disqus-react</code> code snippets for <code>CommentCount</code> and <code>CommentEmbed</code> it is also possible to add those to your Docusaurus project in a similar manner.</p>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="final-observations">Final Observations<a href="https://madrus.dev/blog/blog-comments-2025#final-observations" class="hash-link" aria-label="Direct link to Final Observations" title="Direct link to Final Observations">​</a></h2>
<p>While swizzling is handy, it is still some sort of a patch or workaround. So, if Docusaurus in some future release changes the code or signature of the component, you will probably need to swizzle the new version of the component as well as reapply the patch described here. This has already happened to me once with the <code>BlogPostPage</code> component.</p>
<p>Also, the Docusaurus CLI also evolves. In <code>2.0.0-beta.16</code>,  I was ejecting the complete <code>BlogPostPage</code> component and changing the core code inside. Then in January 2022, there came the <code>--wrap</code> option. Today, in 2025 it did not work for me either, so I used the <code>--dangerous</code> one <!-- -->😄<!-- -->.</p>
<p>Ultimately, adding a comments section via Disqus is more than just a technical implementation; it's about building a vibrant community around your Docusaurus blog. Docusaurus, a robust and well-designed documentation framework, makes this customization possible, providing a clear path to achieve that in 2025 and ensuring your readers have a platform to engage, ask questions, and contribute, even as the framework evolves. Empower your readers to connect with your content today.</p>
<hr>]]></content>
        <author>
            <name>Andre Roussakoff</name>
            <uri>https://github.com/madrus</uri>
        </author>
        <category label="disqus" term="disqus"/>
        <category label="comments" term="comments"/>
        <category label="docusaurus" term="docusaurus"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Knowledge Sharing, the Missing Part]]></title>
        <id>https://madrus.dev/blog/2022-07-05-knowledge-sharing</id>
        <link href="https://madrus.dev/blog/2022-07-05-knowledge-sharing"/>
        <updated>2022-07-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[TL;DR Knowledge is the meat of IT companies. Know-how, architecture, software and DevOps technologies, data, etc. When experienced employees leave, they take their knowledge and experience with them. New employees are hard to find and need time before they learn the skills enough to fill that gap. This poses considerable risks for the continuity and efficiency of any high-tech company and its ability to stay relevant and competitive on the modern market of IT-services. So, knowledge sharing should be very important for IT companies, right? Right.]]></summary>
        <content type="html"><![CDATA[
<p><strong>TL;DR</strong> <strong>Knowledge</strong> is the meat of IT companies. Know-how, architecture, software and DevOps technologies, data, etc. When experienced employees leave, they take their knowledge and experience with them. New employees are hard to find and need time before they learn the skills enough to fill that gap. This poses considerable risks for the continuity and efficiency of any high-tech company and its ability to stay relevant and competitive on the modern market of IT-services. So, <strong>knowledge sharing</strong> should be very important for IT companies, right? Right.</p>
<p>And what about us, developers? Is our primary <strong>motivation</strong> in life keeping afloat the company that employs us? You bet it's not! For most of us, especially young and ambitious, it is much much more personal. Apart from a good salary, it could be fun at work, exciting and challenging tasks, problem solving, professional growth by learning new technologies, being part of a great team, and of course keeping our families happy. If we fail to satisfy our personal needs as developers with the present company, how long will it take before we start looking for new opportunities? <!-- -->😉</p>
<p>So, while <strong>knowledge sharing</strong> has become a crucial survival factor for each IT company, the question is: are we doing it right or is there anything important we are missing? My view is that while the <strong>formal</strong> knowledge sharing process within a company may be well organized, we often overlook something very important: the <strong>personal and social</strong> side of it and its <strong>impact</strong> on the efficiency of the development process.</p>
<p>This article applies to developers of any kind, frontend and backend, as all of them can profit from knowledge sharing. However, the <strong>Missing Part</strong> is probably more applicable to big enterprise level organizations than to small startup companies, which use those types of knowledge sharing techniques anyway.</p>
<!-- -->
<div class="theme-admonition theme-admonition-caution admonition_nV6I alert alert--warning"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>IMPORTANT</div><div class="admonitionContent_vlwu"><p>In this blog post, when I talk about knowledge sharing I am primarily considering ways of doing it face to face. So, it is about meetings, meetups, training sessions, one on one sessions when people have live contact. It is not about individually reading articles and watching training videos to learn about some technical topic.</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="why-knowledge-sharing-is-important">Why Knowledge Sharing is Important<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#why-knowledge-sharing-is-important" class="hash-link" aria-label="Direct link to Why Knowledge Sharing is Important" title="Direct link to Why Knowledge Sharing is Important">​</a></h2>
<p>How do modern devs come about their knowledge? For trainees and junior devs the company can arrange courses related to their job where they can learn some fundamentals like React, TypeScript, C#, .NET framework, Java, and other such big subjects. The experienced senior devs are often able to find solutions even to very tricky issues just by googling. Because they know which search words to choose and they can quickly filter the search results using their vast experience.</p>
<p>The real issue arises in between those two categories, no beginners but also no experts:</p>
<ul>
<li>the devs have insufficient knowledge of what is necessary or even possible</li>
<li>they lack full understanding of the issue at hand</li>
<li>there is no one to go to for immediate help</li>
</ul>
<p>The answer to that issue is the <strong>knowledge sharing</strong>. This blog post is exactly about that.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="conventional-ways-of-knowledge-sharing">Conventional Ways of Knowledge Sharing<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#conventional-ways-of-knowledge-sharing" class="hash-link" aria-label="Direct link to Conventional Ways of Knowledge Sharing" title="Direct link to Conventional Ways of Knowledge Sharing">​</a></h2>
<p>Before we talk about the <strong>Missing Part</strong>, let us summarize more conventional ways of knowledge sharing that many companies use. All of them have one thing in common. They share the same mental model: <strong>GURU to ANYONE</strong>. This model means that one person, a <em>GURU</em>, who "knows it all" shares their knowledge with <em>ANYONE</em>, i.e. normal people who are usually much less experienced and/or lack that knowledge being shared with them.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="course-required-by-the-company-guru-to-anyone">Course Required by the Company (GURU to ANYONE)<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#course-required-by-the-company-guru-to-anyone" class="hash-link" aria-label="Direct link to Course Required by the Company (GURU to ANYONE)" title="Direct link to Course Required by the Company (GURU to ANYONE)">​</a></h3>
<p>This can be seen as an official technical course that every dev employed by the company should follow who does not have that knowledge yet but it is necessary for their daily work. The trainer is usually an external trainer hired by the company. It can be characterized by:</p>
<ul>
<li>may be very expensive but the fees are paid by the company as a loan to the employee;</li>
<li>duration is from 1 day to 1 week;</li>
<li>usually instead of normal work, so participation should be confirmed by management;</li>
<li>certificate of participation at the end;</li>
<li>sometimes an exam and a professional certificate.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="internal-meeting-guru-to-anyone">Internal Meeting (GURU to ANYONE)<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#internal-meeting-guru-to-anyone" class="hash-link" aria-label="Direct link to Internal Meeting (GURU to ANYONE)" title="Direct link to Internal Meeting (GURU to ANYONE)">​</a></h3>
<p>This kind of meeting looks more like a normal meeting (on premise or online) of colleagues involved in the same project(s) or doing similar work. It can be characterized by:</p>
<ul>
<li>regular 1 or 2 hours long team meeting;</li>
<li>meetup type online meeting for everyone interested in the topic(s) shared;</li>
<li>can have a form of a presentation or a workshop;</li>
<li>sessions can be recorded and saved somewhere for later access, also by other team members.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="help-request-guru-to-anyone">Help request (GURU to ANYONE)<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#help-request-guru-to-anyone" class="hash-link" aria-label="Direct link to Help request (GURU to ANYONE)" title="Direct link to Help request (GURU to ANYONE)">​</a></h3>
<p>This is usually a one on one session between a senior dev and a less experienced junior dev. It can be characterized by:</p>
<ul>
<li>occurs strictly upon request of one of the team members;</li>
<li>knowledge sharing is strictly on the "need to know" basis and only for that particular team member who made the request;</li>
<li>the session can be recorded and saved somewhere for later access, also by other team members;</li>
<li>consequently: no request, no knowledge sharing.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="questions-we-ask">Questions We Ask<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#questions-we-ask" class="hash-link" aria-label="Direct link to Questions We Ask" title="Direct link to Questions We Ask">​</a></h3>
<p>In this conventional model, the need for knowledge sharing or decision to participate in a knowledge sharing session may arise from one of the following questions we ask ourselves:</p>
<ul>
<li>Will I learn anything useful I don't know yet? Is it worth my time?</li>
<li>Is it relevant for my work? Will I be able to use it in my project(s)?</li>
<li>If I participate in that session, will I still make the deadline with my current task?</li>
<li>I got stuck in my current task, should I keep trying to find the solution myself or should I make a help request?</li>
</ul>
<p>All these questions have something in common. They are focussed exclusively on our own gain only: "what's in it for me?" And that is exactly the borderline where the <strong>Missing Part</strong> comes in.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="the-missing-part">The Missing Part<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#the-missing-part" class="hash-link" aria-label="Direct link to The Missing Part" title="Direct link to The Missing Part">​</a></h2>
<p>Where the conventional model of knowledge sharing falls short is <strong>the personal growth of devs and the social implications of knowledge sharing</strong>. As we will see, these factors have huge impact on the productivity of devs, the quality of their code, their work satisfaction, creativity, which in fact give a company its competitive edge.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="questions-we-ask-1">Questions We Ask<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#questions-we-ask-1" class="hash-link" aria-label="Direct link to Questions We Ask" title="Direct link to Questions We Ask">​</a></h3>
<p>The questions we ask in the <strong>Missing Part</strong> are quite different from those above. They are much less about <strong>WHAT I CAN GET</strong> and much more about <strong>WHAT I CAN SHARE</strong> and <strong>HOW CAN I CHALLENGE THE STATUS QUO</strong>.</p>
<ul>
<li>I am proud of this piece of my work, can I share it?</li>
<li>this piece of code is fun, can I share it?</li>
<li>this is a very tricky new technique I have used, it is important that my team members know about it. Should I arrange for a 15 minutes knowledge sharing session?</li>
<li>I don't feel comfortable about this piece of code but it is not located in the component I am working on, so formally I should not touch it. Can we at least talk about it?</li>
<li>why is our project structured as it is? I have read about other alternatives. Should I challenge the current solution?</li>
</ul>
<p>Of course, this list of questions is not complete by far but it gives a good idea of the sort of considerations not touched by the conventional guru driven knowledge sharing model.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="what-we-are-missing">What we are missing<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#what-we-are-missing" class="hash-link" aria-label="Direct link to What we are missing" title="Direct link to What we are missing">​</a></h3>
<p>Different teams, different organizations, different ways of working. Here are some personal and social aspects of knowledge sharing. See for yourself, which of them are applicable in your specific team or company.</p>
<ul>
<li>feeling of equality instead of inferiority, especially by junior devs or team members that previously had another specialty;</li>
<li>sense of growth and trust both personally by each team member and the team as a whole;</li>
<li>I have come across something new for myself or something strange, is it safe to ask a question and show my weakness?</li>
<li>what was my/your biggest challenge last week? how have I/you overcome it? if not, can I/you share it with the them/us?</li>
<li>as a (more experienced) dev, I know one of my team members is struggling with a difficult coding task. Should I check on how they are doing?</li>
</ul>
<p>As you can see, these aspects have a lot to do with the safety feeling, caring about other team members and being taken care of if in trouble.</p>
<p>But wait, what does it have to do with the "<em>continuity and efficiency of any high-tech company and its ability to stay relevant and competitive on the modern market of IT-services</em>" we have mentioned above.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="impact-of-missing-the-missing-part">Impact of Missing the Missing Part<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#impact-of-missing-the-missing-part" class="hash-link" aria-label="Direct link to Impact of Missing the Missing Part" title="Direct link to Impact of Missing the Missing Part">​</a></h2>
<div class="theme-admonition theme-admonition-info admonition_nV6I alert alert--info"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>SKIP IF YOU LIKE</div><div class="admonitionContent_vlwu"><p>In this section, I will describe the potential negative impact of missing the <strong>Missing Part</strong> on the company. It is safe to skip the current section if you are only interested in my advice. Go straight to <a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#how-the-missing-part-can-help">How the Missing Part Can Help</a>.</p></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="coding-efficiency">Coding Efficiency<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#coding-efficiency" class="hash-link" aria-label="Direct link to Coding Efficiency" title="Direct link to Coding Efficiency">​</a></h3>
<p>Inefficient coding process leads to more man-hours, higher costs and longer TTM (time to market) for the client. Many non-IT people like managers and product owners believe in a myth that practices like pair programming and knowledge sharing sessions are a waste of billable time. The former because the time spent in man-hours counts twice (two devs working 1 hour together means 2 man-hours), and the latter even more times (10 devs having a 1 hour knowledge sharing session means 10 man-hours with nothing tangible produced). Also, there seems to be the impression that pair programming means hours and days spent by two devs sitting together and staring at one screen.</p>
<p>Why does this myth exist? Primarily because dev work is seen as linear. Meaning that the managers' expectation is that spending twice as much time should produce twice the result (lines of code, tickets, etc.). As devs we know that this is not how we work! Software development requires time for thinking, reading, planning, googling, learning, discussing, and refactoring and does not consist only of routine repeatable work. <!-- -->😃</p>
<p>Another myth is that having devs work each of them 100% on their own is more efficient. Although this can true to some extent for senior devs, it is hardly so for junior devs! The knowledge and experience of senior devs is vast enough to know in advance how to best tackle almost every task at hand. However, when a junior dev picks up a new task, they may face a number of uncertainties:</p>
<ol>
<li>which technique to use? what are the options?</li>
<li>I have some vague idea how to go about it but is my method the right one?</li>
<li>do I know enough about this technique I must use it or should I spend more time learning it first?</li>
<li>if I fail to get the desired result quickly enough, how much time should I keep trying before I ask for help?</li>
<li>everyone else seems to be doing fine with their tickets, if I let them know I need help I will be the only one!</li>
</ol>
<p>Let us consider the corresponding potential negative impact of these uncertainties on the <em>Coding Efficiency</em> in terms of time spent or waisted:</p>
<ol>
<li>time spent on research of the possible options like trying to find similar piece of code in one of the other existing applications;</li>
<li>should the chosen approach finally prove to have been wrong, time has been wasted on the wrong approach;</li>
<li>if I don't know enough, I will first have to spend time to learn the new technique, and even then I still may get stuck when trying to implement it for the first time in my life;</li>
<li>and 5. time spent on trying to solve the task longer than necessary in desperate hope that will save me my face, so I will not have to admit I failed and had to ask for help.</li>
</ol>
<p>Another negative impact is due to the time lost on fixing merge conflicts. Real massive time consuming issues can arise when large changes are uncontrollably merged into the code base while there are other open pull requests (PRs).</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="code-quality">Code quality<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#code-quality" class="hash-link" aria-label="Direct link to Code quality" title="Direct link to Code quality">​</a></h3>
<p>Code quality is not only linting and formatting. Every programming language has its own tools to automatically take care of those. We are talking here about such notions as the <em>code style</em>, how <a href="https://books.google.nl/books?id=UuBU732z6zgC&amp;q=clean+code&amp;dq=clean+code&amp;hl=nl&amp;sa=X&amp;redir_esc=y" target="_blank" rel="noopener noreferrer"><em>clean and modular</em></a> the code is, whether the <a href="https://en.wikipedia.org/wiki/SOLID" target="_blank" rel="noopener noreferrer"><em>S.O.L.I.D. principles</em></a> are observed, and of course <em>code testing</em>. I strongly believe that it is practically impossible to always produce high quality code working 100% individually. The choices we make as devs while coding have to be reviewed and challenged by our peers. PR reviews are a good way to have some control on this but they may not be enough due to <strong>PR fatigue</strong>. Other devs don't always have enough time for thorough analysis, so they may unintentionally approve low quality code.</p>
<p>What is the impact of the low quality code for the company? Potentially it is a time bomb. Its negative effect can grow over time and manifest itself in worse performance, readability, maintainability and robustness. All of which leads to higher future maintenance costs as low quality code adds to the technical debt needing rework some time in the future.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="fun-and-satisfaction--work">Fun and Satisfaction @ Work<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#fun-and-satisfaction--work" class="hash-link" aria-label="Direct link to Fun and Satisfaction @ Work" title="Direct link to Fun and Satisfaction @ Work">​</a></h3>
<p>When devs are bored, don't get enough opportunities for professional growth, don't feel that their work is valued by the peers and the client, and become SCRUM tickets conveyor belt operators, they are more inclined to leave the company having found a more exciting and stimulating job, which many IT startup companies have to offer. Don't forget that enterprise level companies often have a lot of legacy code requiring the knowledge and the usage of outdated techniques.</p>
<p>Lack of knowledge sharing and positive feedback has considerable negative effect on devs, especially the junior devs. It may lead to stress, the feeling of being overwhelmed and having too much on their plate. This can happen when the task itself is unclear or it is unclear how to solve it from the technical point of view. Even bigger stress can arise when the "wrong path" has been chosen. Imagine being busy for a couple of days only to find out that one did the wrong things and the code must be completely rewritten! Or, even worse, it has now to be rewritten by a senior dev to fit into the current sprint. What a waist of energy and a huge disappointment for the first dev!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="how-the-missing-part-can-help">How the Missing Part Can Help<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#how-the-missing-part-can-help" class="hash-link" aria-label="Direct link to How the Missing Part Can Help" title="Direct link to How the Missing Part Can Help">​</a></h2>
<p>Let us now consider the positive impact of adding the <strong>Missing Part</strong> both on the company and on its employees. <em>The effect is like that of spreading the wings, feeling that anything is possible and knowing for sure that it is</em>.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="knowledge-sharing-vs-information-sharing">Knowledge Sharing vs Information sharing<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#knowledge-sharing-vs-information-sharing" class="hash-link" aria-label="Direct link to Knowledge Sharing vs Information sharing" title="Direct link to Knowledge Sharing vs Information sharing">​</a></h3>
<p>Quite often, what we think of as <strong>knowledge sharing</strong> is actually just <strong>information sharing</strong>. These two notions are not one and the same (see, e.g., <a href="https://www.guru99.com/information-vs-knowledge-difference.html" target="_blank" rel="noopener noreferrer">Information vs Knowledge: Key Differences</a>). <em>Information</em> has more to do with presentation of facts and data and being informed about certain subject. <em>Knowledge</em>, on the other hand, while certainly is based on information, has more to do with learning and discovering process and being able to practically use it, either to make conclusions or to create, build something. In that respect, information is rather passive and knowledge is rather active.</p>
<p>The funny thing is that for one person, e.g. a senior dev when they tell about some difficult technique they have used, it is certainly their knowledge they are sharing. But if we look at it with the eyes of a less experienced junior dev, this knowledge can become just information. Imagine that this dev's level of prior knowledge, experience and understanding of the matter is insufficient to grasp the whole picture to say nothing of the small details. For this junior dev to use that technique, they would first need to study it or at least sit together with that senior dev and go through the whole process once again step by step.</p>
<p>If we now look again at the conventional ways of knowledge sharing described above as <strong>GURU to ANYONE</strong> type, we will see something interesting. Although those sessions may indeed be <strong>knowledge sharing</strong> for those participants who have similar level of prior knowledge, they are but <strong>information sharing</strong> for all the others. It would be utopia to expect those others to be able to use that information the next day as their knowledge. Maybe even to remember it!</p>
<p>A good example of this is a PR session. The whole team is looking at the code diffs between the old and the new state. For some team members, especially those who were at one time involved in that particular area, these diffs can be quite meaningful. For other team members it can be just loose bits of information giving them some very general idea about the change.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="mental-shift-guru--anyone">Mental Shift: GURU ⇒ ANYONE<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#mental-shift-guru--anyone" class="hash-link" aria-label="Direct link to Mental Shift: GURU ⇒ ANYONE" title="Direct link to Mental Shift: GURU ⇒ ANYONE">​</a></h3>
<p>This one is my favorite. <!-- -->😃<!-- --> Remember the conventional <strong>GURU to ANYONE</strong> mental model described above? Not every dev feels themselves as being a guru and thus have the urge to share their knowledge. If one looked through the history of the knowledge sharing sessions and the names of their presenters, one would notice that it is a small number of names that repeat many times each. Same devs make presentations. Other devs don't venture.</p>
<p>Let us make a shift to a different mental model: <strong>ANYONE to ANYONE</strong>. This shift makes all the difference in the world! <em>Anyone</em> here means any dev, no matter their level of knowledge and experience. So, according to this new model anyone can share their knowledge. What knowledge? A good question. We know that senior devs can share their knowledge. But what about all the others?</p>
<p>This new way of knowledge sharing requires a <strong>new way of listening</strong> on behalf of the team or colleagues. It requires a more supportive attitude. To illustrate this, I have put the differences in the following table:</p>
<table><thead><tr><th style="text-align:center">Role</th><th>GURU to ANYONE</th><th>ANYONE to ANYONE</th></tr></thead><tbody><tr><td style="text-align:center"><strong>Presenter</strong></td><td>- Is this subject interesting enough?<br>- Does the company require it?<br>- Will I score if I make this presentation?</td><td>- This new technique I learned is fun!<br>- This difficult issue I solved was so tricky!<br>- I see potential value for the team!</td></tr><tr><td style="text-align:center"><strong>Listeners</strong></td><td>- What's in it for me?<br>- Do I need to know this?<br>- The boss requires me to be present <!-- -->😢</td><td>- Let us support our team member!<br>- I know this topic, it's great to talk about it!<br>- Are there any useful tips for the future?</td></tr></tbody></table>
<p>As you can see, the new model is more oriented to support every team member in learning new things, solving difficult issues and telling others about their achievements so that the whole team can celebrate each step in their personal growth as a dev and a professional. And this applies to every team member from a newcomer to a veteran. Knowledge sharing does not have to be related to the application code only. Ik can be anything as long as the Presenter believes that their insights can contribute to the improvement of the team spirit, its efficiency, and professionalism.</p>
<p>Another important feature of it is that these knowledge sharing sessions can be very short and are similar to brainstorming. They can be short because sometimes all it takes to show is just a couple of lines of code or a small tip. <em>Brainstorming</em> follows a very important agreement: <em>nothing is wrong!</em> Meaning that no idea, no matter how crazy or impossible it is, is rejected. Rejection is forbidden! Same here. No matter what kind of idea, technique, tip, or achievement is presented, the team is excited as they witness a step in the professional growth of one of their team members. So, it does not matter if other team members already knew the subject before. These short sessions are always very positive and supportive.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="coding-efficiency-1">Coding Efficiency<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#coding-efficiency-1" class="hash-link" aria-label="Direct link to Coding Efficiency" title="Direct link to Coding Efficiency">​</a></h3>
<p>Let us consider several approaches that stimulate coding efficiency. We have already touched the myths around pair programming above (see <a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#coding-efficiency">Coding Efficiency</a>). Let us now go into it in more details.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="pairing-or-pair-programming">Pairing or Pair programming<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#pairing-or-pair-programming" class="hash-link" aria-label="Direct link to Pairing or Pair programming" title="Direct link to Pairing or Pair programming">​</a></h4>
<p>Pairing or pair programming is not new. To remind you what it is all about, let me cite <strong>Martin Fowler</strong>, a great software guru, from his <a href="https://martinfowler.com/articles/on-pair-programming.html" target="_blank" rel="noopener noreferrer">On Pair Programming</a> article:</p>
<blockquote>
<p>Pair programming essentially means that two people write code together on one machine. It is a very collaborative way of working and involves a lot of communication. While a pair of developers work on a task together, they do not only write code, they also plan and discuss their work. They clarify ideas on the way, discuss approaches and come to better solutions.</p>
</blockquote>
<p>Opposite of what many people think about it, pairing does not necessarily mean that two developers are working on one machine all day long. Each of them can even work primarily on their own ticket but several times a day as necessary they get together for a short session, just a quarter of an hour in order to unblock, to plan, to discuss, or to challenge each other's progress.</p>
<p>Here is one of the possible scenarios:</p>
<ol>
<li>Mark picks up a ticket from the SCRUM board and asks Emmy to be his second.</li>
<li>Emmy picks up another ticket from the SCRUM board and asks Steve (or Mark) to be her second (Steve does the same, etc.).</li>
<li>Mark and Emmy get together for 15 minutes to agree on the approach for Mark.</li>
<li>Emmy and Steve get together to agree on the approach for Emmy.</li>
<li>They repeat these sessions from time to time until the ticket is done, making sure<!-- -->
<ol>
<li>none of them is stuck for longer than 30 minutes<!-- -->
<ol>
<li>if one of them does get stuck, they call their pair for help</li>
<li>if that appears not enough, they both call a more experienced team member for help</li>
</ol>
</li>
<li>the implementation matches the chosen approach</li>
<li>the code quality matched the requirements</li>
<li>the ticket is fully implemented</li>
</ol>
</li>
<li>The ticket is ready for PR only when both devs are happy with it and are both prepared to defend its choices and its code in a PR session.</li>
<li>During the PR session it is the second dev who defends the PR and answers all the questions. Only then everyone can be sure that both devs fully understand the proposed change in the code.</li>
</ol>
<p>In this way, each of the devs works more or less individually but the pair is ready at hand as a standby. By the time the ticket is done, both know everything about the approach, the choices, the reasons, the changes in plan, the motivations, the difficulties and the final code. None of them has got stuck for longer than 30 minutes at any time. It makes it a no-brainer to call for help, fun to plan and work, and the chance of following the wrong path is very low. In other words, this way of working is very efficient and produces high quality results.</p>
<p>It also does not matter who of the two is a more experienced dev. The less experienced dev gets a chance to learn from their more experienced pair. The more experienced one has to make sure that their pair has grown in their knowledge and is ready for PR questions. In a way, the more experienced dev becomes a short term coach for the less experienced one.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="crowd-programming-hackathon-like">Crowd Programming (Hackathon like)<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#crowd-programming-hackathon-like" class="hash-link" aria-label="Direct link to Crowd Programming (Hackathon like)" title="Direct link to Crowd Programming (Hackathon like)">​</a></h4>
<p>This is a variation of the pair programming technique, which I have personally experienced a couple of times. In three hours we have developed and deployed a fully functional prototype of a new CRUD API using C#.NET and MSSQL. It is especially great when a team starts on a new project completely from scratch.</p>
<p>Here is how it works. The whole team of 5-8 people goes to a separate location for several hours. That location has a wall TV mirroring the computer screen and a huge whiteboard. The team has two computers: one for the TV and another one for searching the Internet. There are three roles in the team:</p>
<ul>
<li>The <strong>Coder</strong> is the dev who is writing code on the computer mirrored on the TV</li>
<li>The <strong>Assistant</strong> is the dev who is watching everything Coder is doing and is assisting him (typos, missing details, etc.)</li>
<li>The <strong>Thinkers</strong> are all the other members</li>
</ul>
<p>The complete team starts by drawing the project diagram on the whiteboard until they have a good idea what they need to create. Then they choose the Coder and the Assistant and start the timer for 15 minutes. The Thinkers tell the Coder what to code watching the progress on the TV screen, the Assistant helps the Coder in minor details. If necessary, someone of the Thinkers searches for more clues on the Internet using the second computer.</p>
<p>When the timer stops, the Coder joins the Thinkers, the Assistant becomes the new Coder, and one of the Thinkers becomes the new Assistant. In this way, every team member takes turns in every role. The team may switch from coding to drawing and back again if and when necessary. Very intensive workflow, huge fun, and it quickly produces results on an MVP level.</p>
<p>What is maybe even more important, is that by the end of the session EACH of the team members knows EVERYTHING about the created product, its concept, design, model, code, database, and deployment, so no extra knowledge sharing is necessary after that. <!-- -->😃<!-- --> How exciting!</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="merge-conflicts">Merge conflicts<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#merge-conflicts" class="hash-link" aria-label="Direct link to Merge conflicts" title="Direct link to Merge conflicts">​</a></h4>
<p>There are a couple of rules in regards to merge conflicts that can really save much time and increase work efficiency. The most important one is:</p>
<blockquote>
<p>The devs from both sides of the merge conflict should be involved in the resolution process together to ensure the correct choices.</p>
</blockquote>
<p>This saves time because these two devs have full knowledge of their changes. So none of them needs time to investigate the conflicting code from the other side trying to discern the code intent. This also saves a lot of frustration when later it appears that certain lines of code were wrongly removed or left behind. And then it saves the effort to fix those - well hidden - wrong merge choices.</p>
<p>Next rule:</p>
<blockquote>
<p>Don't let PR's stay open for several days</p>
</blockquote>
<p>When that happens with one PR while other PRs are being merged into the main code base, more and more merge conflicts are accumulating between the open PR and the main code base. So, the consequences described in the previous section become more and more severe. I pity the dev behind the PR staying open for a long time.</p>
<p>Finally:</p>
<blockquote>
<p>When doing massive refactoring, make sure that that PR contains only refactoring and very few to no other changes. Let everyone else merge their PRs first, <strong>freeze</strong> new merges, help the refactoring PR dev solve the merge conflicts, then merge it a.s.a.p. After that everyone starts afresh from the fully refactored code base.</p>
</blockquote>
<p>If you don't do it this way, your team may be facing a nightmare of merge conflicts by those devs who had started their feature branch before the refactoring PR has been merged.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="code-quality-1">Code Quality<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#code-quality-1" class="hash-link" aria-label="Direct link to Code Quality" title="Direct link to Code Quality">​</a></h3>
<p>A lot of what has been said in relation to the <a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#coding-efficiency">Coding Efficiency</a> applies to the Code Quality as well. The most important factor here is the <strong>second opinion</strong>. As has already been said above, PR sessions are after the fact and it can be too late. When the ticket is done and there are many tickets and many PRs, the PR fatigue may kick in. Then it can become practically impossible for the other team members to dive deep enough in each of the PRs because of their sheer number and their own tickets. Especially if the project has to meet a very tough deadline. It can happen that a ticket is done and accepted although the code quality leaves something to desire. If that happens, that PR introduces a new piece of technical debt.</p>
<p>Whereas if each dev uses another dev as their pair, poor choices and poor quality code have much less chance to slip into the code base. And by the time the ticket goes to PR, there are two devs able to defend that ticket who know its every detail. At the same time, this serves as a great quality assurance step firmly built into the development process.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="fun-and-satisfaction--work-1">Fun and Satisfaction @ Work<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#fun-and-satisfaction--work-1" class="hash-link" aria-label="Direct link to Fun and Satisfaction @ Work" title="Direct link to Fun and Satisfaction @ Work">​</a></h3>
<p>When we agree that any dev is welcome to share any insight, whatever concern they might have had whether they are guru enough in a certain area for knowledge sharing, disappears. Every session becomes a <strong>celebration</strong> of a step in the growth process of some team member no matter junior or senior, By the way, doing a presentation is also a step in personal development. Which is very encouraging for each dev no matter their experience.</p>
<p>Regular short knowledge sharing sessions introduce a lot of excitement, pleasure and satisfaction in daily work. Sharing and learning become a new norm. Every dev learns new small tricks all the time, which makes it possible to immediately reuse some of them in their own work.</p>
<p>Imagine the kind of positive impact it can have on the employee turnover. The happy devs who a feeling that they grow as professionals and that they are part of a great team will stay longer! If the company ignores their need for professional growth and happiness at work, they may leave sooner. Then it may become a constant chore of spending time and resources trying to attract new devs and training them only to see them leave again in disappointment shortly after.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="from-theory-to-practice">From Theory to Practice<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#from-theory-to-practice" class="hash-link" aria-label="Direct link to From Theory to Practice" title="Direct link to From Theory to Practice">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="active-knowledge---passive-knowledge--action">Active Knowledge - Passive Knowledge = Action<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#active-knowledge---passive-knowledge--action" class="hash-link" aria-label="Direct link to Active Knowledge - Passive Knowledge = Action" title="Direct link to Active Knowledge - Passive Knowledge = Action">​</a></h3>
<p>The knowledge can be passive or active. When we first learn something, our knowledge becomes passive. It is more like information sharing. We have learned about something but we have not yet mastered it. We have seen things being done but we are not yet able to do it ourselves. Now, in order to make our new knowledge active we need to take <strong>action</strong>. Meaning to build something new based on it or to use it in some project or application we are currently working on.</p>
<p>If we don't, the risk is to forget what we have just learned. Every college or university student knows how quickly the theory is forgotten after the exam is passed! <!-- -->😃<!-- --> In order to make our new knowledge active and persistent, we <strong>must</strong> use it in our work.</p>
<p>I strongly believe that this gives the senior developers a very important coaching role in relation to other, less experienced, team devs. This coaching process may go through the following three phases:</p>
<ol>
<li><strong>SHOW</strong> - show the dev how something is being done (e.g., during the knowledge sharing session)</li>
<li><strong>WATCH</strong> - do it together but let the other dev do it themselves under your supervision</li>
<li><strong>REVIEW</strong> - let them do it completely by themselves and review the final result</li>
</ol>
<blockquote>
<p>NB. this technique is known in The Netherlands as <strong>doe voor, doe mee, doe zelf</strong></p>
</blockquote>
<p>In this way, the senior dev and the team can be 100% sure that the new technique has been really mastered by every team member.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="side-projects">Side Projects<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#side-projects" class="hash-link" aria-label="Direct link to Side Projects" title="Direct link to Side Projects">​</a></h3>
<p>Another exciting way of acquiring and mastering new knowledge is through <strong>side projects</strong>. These are small projects that are not part of our regular work nor projects. When we create an app after app after app for our clients, we tend to use the same techniques all the time. Copy&amp;Paste from the previous app becomes the modus of operation. The risk is to get in a rut and bored. And then the devs start leaving the company...</p>
<p>Side projects give here a breath of fresh air. New ideas, new techniques, new frameworks, new tricks come out every day. It is impossible to learn all of them. Some of them may be potentially useful for our company but we don't know for sure. It is alto too risky to try them out on client projects. But what <strong>is</strong> possible, is to try things out on a micro side project using just that technique or trick or framework. The project should be small enough for a dev to finish it within a couple of days working primarily in their private time, e.g., in the evening or over the weekend. The results can be shared with the team in a knowledge sharing session. For the dev it is a new step in becoming a better professional, and the team may even get a new insight that can be used in the real project.</p>
<p>So, the dev is happy because they have learned something new = have grown professionally, and the team is happy at least for the same reason and maybe because of the new insights. Which in the end is also great for the company and its clients.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="in-conclusion">In Conclusion<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#in-conclusion" class="hash-link" aria-label="Direct link to In Conclusion" title="Direct link to In Conclusion">​</a></h2>
<p>In this blog post, I have demonstrated that the conventional formal knowledge sharing techniques are not enough any more if the company wants to stay relevant and competitive in the modern market. Modern developers, especially the good ones, want to have exciting work and stimulating working conditions. They need incentives to feel great about their work and it is up to the company if they get them. A good salary is not the only important incentive, maybe even not the most important. Having room for professional growth and being supported in their drive to grow, is extremely important for modern devs.</p>
<p>Knowledge sharing is capable to give the devs that great feeling if the <strong>Missing Part</strong> is taken care of and is not missing. They learn new things. they share them freely, other devs share back their discoveries. The new knowledge is being trained and used in side projects. The whole team is supporting and celebrating everyone's growth. If all that is in place who would even think of leaving such a wonderful company!!! <!-- -->😃</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="references">References<a href="https://madrus.dev/blog/2022-07-05-knowledge-sharing#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References">​</a></h2>
<ul>
<li>For some interesting insights on knowledge sharing inside enterprise organizations, listen to this podcast show: <a href="http://podrocket.logrocket.com/modern-react-repeat" target="_blank" rel="noopener noreferrer">Modern React with Paige Niedringhaus</a>.</li>
<li>The Robert C. Martin's <a href="https://books.google.nl/books?id=UuBU732z6zgC" target="_blank" rel="noopener noreferrer">Clean Code Collection</a></li>
<li><a href="https://www.guru99.com/information-vs-knowledge-difference.html" target="_blank" rel="noopener noreferrer">Information vs Knowledge: Key Differences</a></li>
<li>Martin Fowler's <a href="https://martinfowler.com/articles/on-pair-programming.html" target="_blank" rel="noopener noreferrer">On Pair Programming</a></li>
<li>Recently, I have come across an article of Carmo Braga da Costa <a href="https://dev.to/carmonara/how-to-improve-knowledge-sharing-in-your-engineering-org-and-beyond-1ae7" target="_blank" rel="noopener noreferrer">How to Improve Knowledge Sharing In Your Engineering Org. (and beyond)</a>. She gives an interesting view on Knowledge Sharing from the organizational point of view. Read her view on Risks and her advice on improving the Knowledge Sharing. This bit is my favorite:<!-- -->
<blockquote>
<p>Putting your efforts into improvements takes away time from delivering things. But deprioritizing the dissemination of knowledge across teams can lead to complicated risks, which sooner or later will catch up with you.</p>
</blockquote>
</li>
</ul>
<hr>]]></content>
        <author>
            <name>Andre Roussakoff</name>
            <uri>https://github.com/madrus</uri>
        </author>
        <category label="knowledge sharing" term="knowledge sharing"/>
        <category label="team" term="team"/>
        <category label="social" term="social"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Add Disqus Comments to Docusaurus Blog Posts (archived)]]></title>
        <id>https://madrus.dev/blog/blog-comments</id>
        <link href="https://madrus.dev/blog/blog-comments"/>
        <updated>2021-01-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[TL;DR Recently I have switched from Jekyll to Docusaurus for my personal website. And immediately noticed the issue with letting the visitors place comments to blog posts. It seems that the comments work out of the box only for Facebook comments and then only if one has a registered FB business site (according to this PR). Searching on adding e.g. Disqus blog comments in Docusaurus brought back more questions than answers. (see some references at the end of this post)]]></summary>
        <content type="html"><![CDATA[<p><strong>TL;DR</strong> Recently I have switched from <a href="https://jekyllrb.com/" target="_blank" rel="noopener noreferrer">Jekyll</a> to <a href="https://v2.docusaurus.io/" target="_blank" rel="noopener noreferrer">Docusaurus</a> for my personal website. And immediately noticed the issue with letting the visitors place comments to blog posts. It seems that the comments work out of the box only for Facebook comments and then only if one has a registered FB business site (according to this <a href="https://github.com/facebook/docusaurus/pull/673" target="_blank" rel="noopener noreferrer">PR</a>). Searching on adding e.g. <a href="https://disqus.com/" target="_blank" rel="noopener noreferrer">Disqus</a> blog comments in Docusaurus brought back more questions than answers. (see some references at the end of this post)</p>
<p>The closest I could get to the solution was <a href="https://www.coderhackers.com/blog/2020/02/29/how-to-add-forum-to-docusaurus/" target="_blank" rel="noopener noreferrer">How to add forum to Docusaurus</a> using <a href="https://utteranc.es/" target="_blank" rel="noopener noreferrer">Utterances</a> comments via GitHub issues. I got the gist but the vendor binding was too big to my taste.</p>
<p>So, I have made my own go on this issue and finally succeeded in adding the Disqus blog comments to my Docusaurus blog. In this blog post you can see them in action and also read how I did it. I hope it might help some of you to do the same on yours.</p>
<div class="theme-admonition theme-admonition-important admonition_nV6I alert alert--info"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>UPDATED July 12, 2022</div><div class="admonitionContent_vlwu"><p>The code examples are compatible with Docusaurus <code>2.0.0-beta.16</code> and higher</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="lets-go">Let's Go<a href="https://madrus.dev/blog/blog-comments#lets-go" class="hash-link" aria-label="Direct link to Let's Go" title="Direct link to Let's Go">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="prerequisites">Prerequisites<a href="https://madrus.dev/blog/blog-comments#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites">​</a></h3>
<p>You will need the following things in place to have ready to get the job done:</p>
<ol>
<li>your project must be running Docusaurus v2 with at least one blog post;</li>
<li>you have installed your project using <code>theme-classic</code></li>
<li>a terminal session open in the root of your project;</li>
<li>an account with <a href="https://disqus.com/" target="_blank" rel="noopener noreferrer">Disqus</a> with your registered Docusaurus web-app.</li>
</ol>
<p>Install <code>disqus-react</code>:</p>
<div class="language-bash codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-bash codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">pnpm add disqus-react</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">npm add disqus-react</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">yarn add disqus-react</span><br></span></code></pre></div></div>
<p>If you need some guidance on Disqus weblog registration, see my <a href="https://madrus.dev/blog/register-disqus">Register Your Weblog with Disqus</a> section below.</p>
<hr>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="prepare-the-frontmatter">Prepare the Frontmatter<a href="https://madrus.dev/blog/blog-comments#prepare-the-frontmatter" class="hash-link" aria-label="Direct link to Prepare the Frontmatter" title="Direct link to Prepare the Frontmatter">​</a></h3>
<p>Run your Docusaurus project locally running either <code>yarn start</code> or <code>npm run start</code> in your terminal. Browse to <a href="http://localhost:3000/blog" target="_blank" rel="noopener noreferrer">http://localhost:3000/blog</a> and make sure you see at least one blog post. Choose one of them to work with.</p>
<p>Open the chosen blog post file in your editor of choice and add the following two lines at the end of the frontmatter:</p>
<div class="language-yaml codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-yaml codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">slug</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> your</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">blog</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">post</span><span class="token punctuation" style="color:rgb(199, 146, 234)">-</span><span class="token plain">slug</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">draft</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token key atrule">comments</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> </span><span class="token boolean important" style="color:rgb(255, 88, 116)">true</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic"># for Disqus</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">---</span><br></span></code></pre></div></div>
<p>It is a good idea to keep <code>draft</code> value as <code>true</code> until you know for sure everything works fine. What it does is that it lets you see your post while running Docusaurus on localhost. But if you publish your branch to the web, this particular blog post won't be published and visible. When you are ready, you can set it to <code>false</code> or remove completely from the frontmatter.</p>
<p>The second <code>comments</code> property lets you decide for each blog post if you want your visitors leave comments. Set it to <code>false</code> and there will be no Disqus comments section underneath your blog post. Without this property or with it explicitly set to <code>true</code> the comments section will be present by default.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="swizzle-the-blogpostitem-component">Swizzle the BlogPostItem component<a href="https://madrus.dev/blog/blog-comments#swizzle-the-blogpostitem-component" class="hash-link" aria-label="Direct link to Swizzle the BlogPostItem component" title="Direct link to Swizzle the BlogPostItem component">​</a></h3>
<p><a href="https://docusaurus.io/docs/swizzling" target="_blank" rel="noopener noreferrer"><strong>Swizzling</strong></a> a Docusaurus component means either adding a wrapper for or including the source code of a core component into your project. This allows us to customize the component's functionality. The application will then use the swizzled and customized version of the component instead of the standard one. In our case, we will be using swizzling to add the Disqus comments on our blog post pages.</p>
<p>Following the tip about adding comments on the Swizzling page, let us wrap the <code>BlogPostItem</code> component. Run the following command and accept the warning about the risks:</p>
<div class="language-bash codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-bash codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">pnpm swizzle @docusaurus/theme-classic BlogPostItem -- --wrap</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">npm run swizzle @docusaurus/theme-classic BlogPostItem -- --wrap</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"># or</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">yarn swizzle @docusaurus/theme-classic BlogPostItem -- --wrap</span><br></span></code></pre></div></div>
<p>If your project uses TypeScript, add an extra <code>--typescript</code> flag at the end of the command line. This will copy the TypeScript version of the component and its <code>index.d.ts</code> types file.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="discussionembed">DiscussionEmbed<a href="https://madrus.dev/blog/blog-comments#discussionembed" class="hash-link" aria-label="Direct link to DiscussionEmbed" title="Direct link to DiscussionEmbed">​</a></h3>
<p>Open the <code>index.js</code> file inside and let us add our custom code. I have roughly followed the instruction from the <a href="https://github.com/disqus/disqus-react" target="_blank" rel="noopener noreferrer">disqus-react</a> repository but changed the code a bit to include the <code>comments</code> property and to add the missing details of integration with Docusaurus.</p>
<p>Replace the contents of the swizzled <code>src/theme/BlogPostItem/index.js</code> with the following code:</p>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockTitle_dgyJ">/src/theme/BlogPostItem/index.ts</div><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">DiscussionEmbed</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'disqus-react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> useBlogPost </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@docusaurus/theme-common/internal'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">BlogPostItem</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@theme-original/BlogPostItem'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">default</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(130, 170, 255)">BlogPostItemWrapper</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter">props</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> metadata </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useBlogPost</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> frontMatter</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> slug</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> title </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> metadata</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> comments </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> frontMatter</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag class-name" style="color:rgb(255, 203, 107)">BlogPostItem</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag spread punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token tag spread" style="color:rgb(255, 85, 114)">props</span><span class="token tag spread punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">comments </span><span class="token operator" style="color:rgb(137, 221, 255)">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag class-name" style="color:rgb(255, 203, 107)">DiscussionEmbed</span><span class="token tag" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag" style="color:rgb(255, 85, 114)">          </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">shortname</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">your-disqus-shortname</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag" style="color:rgb(255, 85, 114)">          </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">config</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">            </span><span class="token tag script language-javascript literal-property property" style="color:rgb(255, 85, 114)">url</span><span class="token tag script language-javascript operator" style="color:rgb(137, 221, 255)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"> slug</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">            </span><span class="token tag script language-javascript literal-property property" style="color:rgb(255, 85, 114)">identifier</span><span class="token tag script language-javascript operator" style="color:rgb(137, 221, 255)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"> slug</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">            title</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">            </span><span class="token tag script language-javascript literal-property property" style="color:rgb(255, 85, 114)">language</span><span class="token tag script language-javascript operator" style="color:rgb(137, 221, 255)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"> </span><span class="token tag script language-javascript string" style="color:rgb(195, 232, 141)">'en_US'</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">          </span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token tag" style="color:rgb(255, 85, 114)">        </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>If your web application has been properly registered with Disqus, you should see the Disqus comments appear under every blog post. Once you got it working locally you may set <code>draft: false</code> in the frontmatter or remove the setting completely and publish your project. The comments block will be there as well.</p>
<div class="theme-admonition theme-admonition-caution admonition_nV6I alert alert--warning"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><div class="admonitionContent_vlwu"><p>The comments you add when testing your website locally do not synchronize with the comments of the same deployed page.</p></div></div>
<div class="theme-admonition theme-admonition-danger admonition_nV6I alert alert--danger"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>DO NOT CHANGE YOUR SLUGS</div><div class="admonitionContent_vlwu"><p>Be careful with changing slugs. Your existing comments are connected to it. If you change the slug, you will loose them. If that happens, just restore the old slug.</p></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="commentcount-and-commentembed">CommentCount and CommentEmbed<a href="https://madrus.dev/blog/blog-comments#commentcount-and-commentembed" class="hash-link" aria-label="Direct link to CommentCount and CommentEmbed" title="Direct link to CommentCount and CommentEmbed">​</a></h3>
<p>Using the <code>disqus-react</code> code snippets for <code>CommentCount</code> and <code>CommentEmbed</code> it is also possible to add those to your Docusaurus project in a similar manner.</p>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="final-observations">Final Observations<a href="https://madrus.dev/blog/blog-comments#final-observations" class="hash-link" aria-label="Direct link to Final Observations" title="Direct link to Final Observations">​</a></h2>
<p>While swizzling is handy, it is still some sort of a patch or workaround. So, if Docusaurus in some future release changes the code or signature of the component, you will probably need to swizzle their new versions. Meaning that you will also need to reapply the patch described here.</p>
<p>This has already happened in Docusaurus <code>2.0.0-beta.16</code>. In the initial version of this article in January 2021, I was ejecting the <code>BlogPostPage</code> component and changing the core code inside. At that time, there was no wrapping option. Then in January 2022, Sébastien Lorber, one of the maintainers of Docusaurus, posted this comment:</p>
<blockquote>
<p>Docusaurus maintainer here, thanks for the blog post.
Note that in 2022 and for the v2 release we'll improve and make this easier to add comments.</p>
<p>Basically, instead of copying internal implementation details, you'll just "wrap" an existing component (like BlogContent) to add your comment system just under <a href="https://docusaurus.io/docs/..." target="_blank" rel="noopener noreferrer">https://docusaurus.io/docs/...</a></p>
<p>We are working on a new "docusaurus swizzle --wrap" CLI to encourage this pattern, and thinking about good component granularity so that this pattern can be useful to solve many use-cases</p>
</blockquote>
<p>Thanks to Sébastien, I have used this new wrapping option and updated the blog post accordingly.</p>
<hr>]]></content>
        <author>
            <name>Andre Roussakoff</name>
            <uri>https://github.com/madrus</uri>
        </author>
        <category label="disqus" term="disqus"/>
        <category label="comments" term="comments"/>
        <category label="docusaurus" term="docusaurus"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Register Your Weblog with Disqus]]></title>
        <id>https://madrus.dev/blog/register-disqus</id>
        <link href="https://madrus.dev/blog/register-disqus"/>
        <updated>2021-01-09T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[TL;DR Many of us have Disqus account to be able to place comments on those blogs which use Disqus comments widget for that. Because placing comments often requires being logged in. Of course, you can also log in with your Twitter or Facebook account. What is nice of Disqus optioin is that it keeps track of all your comments placed anywhere.]]></summary>
        <content type="html"><![CDATA[<p><strong>TL;DR</strong> Many of us have Disqus account to be able to place comments on those blogs which use <a href="https://disqus.com/" target="_blank" rel="noopener noreferrer">Disqus</a> comments widget for that. Because placing comments often requires being logged in. Of course, you can also log in with your Twitter or Facebook account. What is nice of Disqus optioin is that it keeps track of all your comments placed anywhere.</p>
<p>Sometimes however we want to add Disqus comments to our own blog and that requires another type of registration: that of our weblog itself. In this article, I share how this can be done. It may be helpful for those of you who got lost on the Disqus website searching for clues. <!-- -->😃</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="disqus-registration">Disqus Registration<a href="https://madrus.dev/blog/register-disqus#disqus-registration" class="hash-link" aria-label="Direct link to Disqus Registration" title="Direct link to Disqus Registration">​</a></h2>
<ol>
<li>Register and account with <a href="https://disqus.com/" target="_blank" rel="noopener noreferrer">Disqus</a> if you don't have one yet.</li>
<li>Log in to your account.</li>
<li>If it is the first time you are logging in, you will immediately get to see the screen as in step no.8. Otherwise, proceed to step no.4.</li>
<li>In the <code>Admin</code> section create your organization (any name you like).</li>
<li>Click on your avatar and choose <code>Settings</code>. You will now see the gear icon next to it.</li>
<li>Click on the gear icon and choose <code>Add Disqus to Site</code>:</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Add Disqus to site" src="https://madrus.dev/assets/images/add-disqus-to-site-d9d92ae294217351d8564e99dfa277f2.png" width="139" height="278" class="img_y867"></p>
<ol start="7">
<li>Scroll to the bottom of the page till you see the <span style="background-color:#2E9FFF;color:white;padding:0.75rem 1rem;font-size:0.8rem;font-weight:700;border-radius:3px">GET STARTED</span> button. Click on it.</li>
<li>Now choose the <code>I want to install Disqus on my site</code> option.</li>
<li>Fill in the form:</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Create a new site" src="https://madrus.dev/assets/images/create-disqus-site-cd5e4fe1b967a02c23ffb66a5c4c4719.png" width="651" height="617" class="img_y867"></p>
<p>You may click the <code>Customize Your URL</code> link for more information on how to choose the <code>Website Name</code>.</p>
<ol start="10">
<li>When you fill in all the fields, click the the <span style="background-color:#2E9FFF;color:white;padding:0.7rem 1.5rem;font-size:0.8rem;font-weight:700;border-radius:3px">Create Site</span> button.</li>
<li>On the next page your will be presented with the Disqus paid plans. Just scroll down to the free Basic plan and click on the <kbd>Subscribe Now</kbd> button:</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Subscribe to Basic plan" src="https://madrus.dev/assets/images/subscrbe-now-070e7d6c1e4e13b895c86b6fda61a195.png" width="367" height="244" class="img_y867"></p>
<ol start="12">
<li>Now you will be presented with a big choice of platforms to install Disqus on. Docusaurus is not one of them, so choose</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Install manually with Universal Code" src="https://madrus.dev/assets/images/universal-code-73001dda263a6cec0b728d9c603d41a3.png" width="503" height="106" class="img_y867"></p>
<p>Ignore the next page.</p>
<ol start="13">
<li>Click on the <code>Configure Disqus</code> menu option in the side menu on the left. This one is important. Here you have to specify your real <code>Website URL</code> to make sure that Disqus will collect the comments coming from that domain. Click the <span style="background-color:#2E9FFF;color:white;padding:0.7rem 1.5rem;font-size:0.8rem;font-weight:700;border-radius:3px">Next</span> button.</li>
<li>Now, in <code>Setup Moderation</code> choose the default settings profile to moderate the comments of your visitors. Click the <span style="background-color:#2E9FFF;color:white;padding:0.7rem 1.5rem;font-size:0.8rem;font-weight:700;border-radius:3px">Complete Setup</span> button.</li>
</ol>
<p>You are done! Now, you will see the Disqus comments section under your blog posts. However...</p>
<div class="theme-admonition theme-admonition-danger admonition_nV6I alert alert--danger"><div class="admonitionHeading_OJm8"><span class="admonitionIcon_xiKe"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>Extra Moderation Settings</div><div class="admonitionContent_vlwu"><p>Make sure you configure the special <code>Comment &amp; Moderation Settings</code> section for your website!</p></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="disqus-moderation-policies">Disqus Moderation Policies<a href="https://madrus.dev/blog/register-disqus#disqus-moderation-policies" class="hash-link" aria-label="Direct link to Disqus Moderation Policies" title="Direct link to Disqus Moderation Policies">​</a></h2>
<p>In the Admin portal of your newly registered website, go to Moderation Settings:</p>
<p><img decoding="async" loading="lazy" alt="Open Moderation Settings" src="https://madrus.dev/assets/images/admin-settings-4a37191e13cae4a03bb9e24940e39e23.png" width="739" height="340" class="img_y867"></p>
<p>Now, go through the <code>Moderation Settings</code> and make sure you checkmark the options you believe are important to have:</p>
<p><img decoding="async" loading="lazy" alt="Choose Moderation Settings" src="https://madrus.dev/assets/images/moderation-settings-9812a16192e095735ba47323fdfc4a81.png" width="853" height="462" class="img_y867"></p>
<p>For me personally, the most difficult choice is that of <code>Pre-moderation</code>. Without it you may get spam comments published under your blog post. With it you may frighten away visitors who don't want to be censored. I would rather prefer a rule which requires any new visitor to have only his very first comment moderated and, if accepted, no more moderation for all their comments afterwards.</p>
<hr>]]></content>
        <author>
            <name>Andre Roussakoff</name>
            <uri>https://github.com/madrus</uri>
        </author>
        <category label="disqus" term="disqus"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[How GraphQL Query Passes its Response Back to Gatsby React Components]]></title>
        <id>https://madrus.dev/blog/graphql-response-to-gatsby-react</id>
        <link href="https://madrus.dev/blog/graphql-response-to-gatsby-react"/>
        <updated>2019-12-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[TL;DR When I started learning Gatsby, I wanted to understand the magic of GraphQL queries passing their results back to the React component. My secondary focus was to use React functional components instead of React class components as much as possible. In this blogpost, I have summarized my findings.]]></summary>
        <content type="html"><![CDATA[<p><strong>TL;DR</strong> When I started learning Gatsby, I wanted to understand the magic of GraphQL queries passing their results back to the React component. My secondary focus was to use React functional components instead of React class components as much as possible. In this blogpost, I have summarized my findings.</p>
<p>Most of the information comes from <a href="https://www.gatsbyjs.org/docs/" target="_blank" rel="noopener noreferrer">Gatsby Documentation</a> and from my personal test projects.</p>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="page-query">Page Query<a href="https://madrus.dev/blog/graphql-response-to-gatsby-react#page-query" class="hash-link" aria-label="Direct link to Page Query" title="Direct link to Page Query">​</a></h2>
<p>Suppose we have our site metadata defined in <code>gatsby-config.js</code>:</p>
<div class="language-js codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-js codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">siteMetadata</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">title</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"My Personal website"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">description</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"The most wonderful description of my website goes here."</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>Then in the <code>src/pages/HomePage.js</code> (or <code>index.js</code>) we can write the following code, which will show the description <code>The most wonderful description of my website goes here.</code> on the page:</p>
<div class="language-js codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-js codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> graphql </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'gatsby'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token function-variable function maybe-class-name" style="color:rgb(130, 170, 255)">HomePage</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token parameter">data</span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token plain">div</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">     </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">site</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">siteMetadata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">description</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">div</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> query </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> graphql</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">  </span><span class="token template-string graphql language-graphql keyword" style="font-style:italic">query</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql definition-query function" style="color:rgb(130, 170, 255)">HomePageQuery</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">    </span><span class="token template-string graphql language-graphql object">site</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">      </span><span class="token template-string graphql language-graphql object">siteMetadata</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">        </span><span class="token template-string graphql language-graphql property">description</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">      </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">    </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">  </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql"></span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">default</span><span class="token plain"> </span><span class="token maybe-class-name">HomePage</span><br></span></code></pre></div></div>
<p>So, where does the <code>HomePage</code> function get its <code>data</code> from? Here we have the famous "Convention over Configuration" principle at work:</p>
<ol>
<li>the <code>site</code> field in the GraphQL query refers to the <code>gatsby-config.js</code> file above; the <code>siteMetadata</code> object with the <code>description</code> field gets exported there;</li>
<li>the GraphQL query itself is (and should be!) also exported: <code>export const query = graphql</code>;</li>
<li>as a result, the query response is passed as the <code>data</code> prop to the <code>HomePage</code> function and can be destructured  as <code>{ data }</code> from its props.</li>
</ol>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="page-query-with-query-variables">Page Query with Query Variables<a href="https://madrus.dev/blog/graphql-response-to-gatsby-react#page-query-with-query-variables" class="hash-link" aria-label="Direct link to Page Query with Query Variables" title="Direct link to Page Query with Query Variables">​</a></h2>
<p>With page queries we can go a step further and add query variables to the GraphQL query. The following example shows how it can be done. It is extra interesting because it is also an example of how to query the <code>.mdx</code> pages in our project.</p>
<p>Let us look at this query in the <code>src/templates/blog-post.js</code> file:</p>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> query </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> graphql</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">  </span><span class="token template-string graphql language-graphql keyword" style="font-style:italic">query</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql definition-query function" style="color:rgb(130, 170, 255)">MdxBlogPost</span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token template-string graphql language-graphql variable" style="color:rgb(191, 199, 213)">$title</span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql scalar">String</span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">    </span><span class="token template-string graphql language-graphql property-query">mdx</span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token template-string graphql language-graphql attr-name" style="color:rgb(255, 203, 107)">title</span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql attr-name" style="color:rgb(255, 203, 107)">eq</span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql variable" style="color:rgb(191, 199, 213)">$title</span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">      </span><span class="token template-string graphql language-graphql property">id</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">      </span><span class="token template-string graphql language-graphql property">title</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">    </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">  </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql"></span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><br></span></code></pre></div></div>
<p>It uses <code>$title</code> as a variable and searches the MDX-nodes in the project site with the <code>title</code> that equals the <code>$title</code> string value.</p>
<blockquote>
<p>For this to work,</p>
<ul>
<li>
<p>the <code>MdxBlogPost</code> query should have <code>gatsby-plugin-mdx</code> plugin installed, and</p>
</li>
<li>
<p>serving of the <code>.mdx</code> files should be configured via <code>gatsby-source-filesystem</code> plugin in the <code>gatsby-config.js</code> file.</p>
</li>
</ul>
</blockquote>
<p>When a page is created dynamically from the blog post template in <code>gatsby-node.js</code>, you can provide an <em>object</em> as part of the page’s context. Keys in the context object that match up with arguments in the page query (in this case: <code>"title"</code>), will be used as variables. Variables are prefaced with <code>$</code>, so passing a <code>title</code> property will become<code>$title</code> in the query.</p>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">posts</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">forEach</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token parameter"> node </span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token parameter"> index</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token function" style="color:rgb(130, 170, 255)">createPage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">path</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> node</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">fields</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">slug</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">component</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">resolve</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">./src/templates/blog-post.js</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// values in the context object are passed in as variables to page queries</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">context</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token literal-property property">title</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> node</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">title</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// "The most wonderful description ..."</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="staticquery">StaticQuery<a href="https://madrus.dev/blog/graphql-response-to-gatsby-react#staticquery" class="hash-link" aria-label="Direct link to StaticQuery" title="Direct link to StaticQuery">​</a></h2>
<p>Gatsby v2 introduced <code>StaticQuery</code>, a new API that allowed not only pages but  <strong>any component</strong> to retrieve data via a GraphQL query.</p>
<p>The table below shows the differences between page queries and the StaticQuery element.</p>
<table><thead><tr><th>Page Query</th><th>StaticQuery</th></tr></thead><tbody><tr><td>works only in Pages</td><td>works in any React component including Pages</td></tr><tr><td>accepts variables via <code>pageContext</code></td><td>accepts no variables</td></tr><tr><td>works with <code>React.createElement</code></td><td>does not work with <code>React.createElement</code>, instead it is itself a JSX <code>&lt;StaticQuery /&gt;</code> element</td></tr><tr><td>default export: the page <code>query </code>  itself</td><td>default export: an anonymous function, which returns the <code>StaticQuery</code> element</td></tr></tbody></table>
<p>Simply said the <code>StaticQuery</code> is a JSX-element with 2 parameters:</p>
<ul>
<li><code>query</code> that holds a query definition, and</li>
<li><code>render</code> that holds a function returning a JSX-element</li>
</ul>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag class-name" style="color:rgb(255, 203, 107)">StaticQuery</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">query</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 85, 114)">graphql</span><span class="token tag script language-javascript template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token tag script language-javascript template-string graphql language-graphql operator" style="color:rgb(137, 221, 255)">...</span><span class="token tag script language-javascript template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">render</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><br></span></code></pre></div></div>
<p>It handles the query result in a different way than a page query. Let us consider the following code snippet:</p>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"react"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">StaticQuery</span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token imports"> graphql </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"gatsby"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">default</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">&lt;</span><span class="token maybe-class-name">StaticQuery</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    query</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">graphql</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">      </span><span class="token template-string graphql language-graphql keyword" style="font-style:italic">query</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql definition-query function" style="color:rgb(130, 170, 255)">HeadingQuery</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">        </span><span class="token template-string graphql language-graphql object">site</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">          </span><span class="token template-string graphql language-graphql object">siteMetadata</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">            </span><span class="token template-string graphql language-graphql property">title</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">          </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">        </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">      </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">    </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    render</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token parameter">data</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">header</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">h1</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">site</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">siteMetadata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">title</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">h1</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">header</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<p>How it works is that the <strong>result</strong> of the query in the <code>query</code> parameter automagically becomes the <strong>value</strong> of the <code>render</code> function <code>data</code> argument.</p>
<blockquote>
<p>Notice the <code>export default () =&gt; (...)</code> signature similar to that of the page query except that here we have an <strong>anonymous</strong> default export.</p>
</blockquote>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="from-staticquery-to-usestaticquery-hook">From StaticQuery to useStaticQuery hook<a href="https://madrus.dev/blog/graphql-response-to-gatsby-react#from-staticquery-to-usestaticquery-hook" class="hash-link" aria-label="Direct link to From StaticQuery to useStaticQuery hook" title="Direct link to From StaticQuery to useStaticQuery hook">​</a></h2>
<p>React hooks are becoming more and more popular, and Gatsby has created its own: <strong>useStaticQuery</strong> hook. It is based on the <code>StaticQuery</code> element and requires at least version 16.8.0 of <code>React</code> and <code>ReactDOM</code>packages. Let us rewrite the previous example using this hook:</p>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"react"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> useStaticQuery</span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token imports"> graphql </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"gatsby"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">default</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> data </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">useStaticQuery</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">graphql</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">    </span><span class="token template-string graphql language-graphql keyword" style="font-style:italic">query</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql definition-query function" style="color:rgb(130, 170, 255)">HeaderQuery</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">      </span><span class="token template-string graphql language-graphql object">site</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">        </span><span class="token template-string graphql language-graphql object">siteMetadata</span><span class="token template-string graphql language-graphql"> </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">          </span><span class="token template-string graphql language-graphql property">title</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">        </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">      </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">    </span><span class="token template-string graphql language-graphql punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string graphql language-graphql"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token template-string graphql language-graphql">  </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">header</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">h1</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">site</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">siteMetadata</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">title</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">h1</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">header</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>Here, we extract <code>data</code> object from the <code>useStaticQuery</code> hook and then use it in the JSX-element we return from the default anonymous export.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="known-limitations-of-usestatic-query">Known Limitations of useStatic Query<a href="https://madrus.dev/blog/graphql-response-to-gatsby-react#known-limitations-of-usestatic-query" class="hash-link" aria-label="Direct link to Known Limitations of useStatic Query" title="Direct link to Known Limitations of useStatic Query">​</a></h3>
<p>As Gatsby documentation states, <code>useStaticQuery</code></p>
<ul>
<li>does not accept variables (hence the name “static”), but can be used in any component, including pages;</li>
<li>because of how queries currently work in Gatsby, only a <strong>single instance</strong> of <code>useStaticQuery</code> per file is supported.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="closing-words">Closing Words<a href="https://madrus.dev/blog/graphql-response-to-gatsby-react#closing-words" class="hash-link" aria-label="Direct link to Closing Words" title="Direct link to Closing Words">​</a></h2>
<p>We have considered three options how to use GraphQL in Gatsby:</p>
<ul>
<li>Page Queries to use only on pages</li>
<li>StaticQuery to use in any JSX-component</li>
<li>useStaticQuery hook to use in any JSX-component</li>
</ul>
<p>For every option we have shown how the query result is passed to the corresponding presentational component.</p>
<hr>]]></content>
        <author>
            <name>Andre Roussakoff</name>
            <uri>https://github.com/madrus</uri>
        </author>
        <category label="Gatsby" term="Gatsby"/>
        <category label="GraphQL" term="GraphQL"/>
        <category label="JavaScript" term="JavaScript"/>
        <category label="StaticQuery" term="StaticQuery"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Storybook React - DocsPage+MDX and Notes+MD with Typescript]]></title>
        <id>https://madrus.dev/blog/storybook-setup-docspages-and-mdx</id>
        <link href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx"/>
        <updated>2019-11-23T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[TL;DR When I came across the Storybook project as a way to create a standard design system, I have very quickly realized that many of the code snippets in the official documentation don't work out of the box if using Typescript. My focus however was on setting up the Storybook DocsPage + MDX and Storybook Notes + Markdown with Typescript. In this blog post you can read how I got everything working. First, Notes with Markdown. Then DocsPage with MDX.]]></summary>
        <content type="html"><![CDATA[<p><strong>TL;DR</strong> When I came across the <a href="https://storybook.js.org/" target="_blank" rel="noopener noreferrer">Storybook</a> project as a way to create a standard design system, I have very quickly realized that many of the code snippets in the <a href="https://storybook.js.org/docs/guides/guide-react/" target="_blank" rel="noopener noreferrer">official documentation</a> don't work out of the box if using <a href="https://www.typescriptlang.org/index.html" target="_blank" rel="noopener noreferrer">Typescript</a>. My focus however was on setting up the <a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/README.md" target="_blank" rel="noopener noreferrer">Storybook DocsPage + MDX</a> and <a href="https://devstore.io/js/@storybook/addon-docs" target="_blank" rel="noopener noreferrer">Storybook Notes + Markdown</a> with Typescript. In this blog post you can read how I got everything working. First, <a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#notes-with-markdown">Notes with Markdown</a>. Then <a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#docspage-with-mdx">DocsPage with MDX</a>.</p>
<hr>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="keep-in-mind">Keep in mind<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#keep-in-mind" class="hash-link" aria-label="Direct link to Keep in mind" title="Direct link to Keep in mind">​</a></h2>
<p>In the beginning, when I added Typescript many things broke and stopped working, so I have had to search on Google and have tried a whole bunch of different tips and tricks. Of course, most of them come from the Storybook documentation, Storybook blog posts, and StackOverflow. By the time I got stuff working, I did not know any more, which tip I found where. Even if <em>everything</em> I added was really necessary. So feel free to remove some additions if you think they don't make sense.</p>
<p>We are using <code>YARN</code> all over the project, so you will see a lot of <code>yarn</code> commands. If you prefer <code>NPM</code>, just replace <code>yarn add</code> with <code>npm i</code> to install stuff, and <code>yarn &lt;some script from package.json&gt;</code> with <code>npm run &lt;same script from package.json&gt;</code> and you are good to go. :-)</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="typescript-stuff">Typescript stuff<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#typescript-stuff" class="hash-link" aria-label="Direct link to Typescript stuff" title="Direct link to Typescript stuff">​</a></h2>
<p>Here is the <code>tsconfig.json</code> in the root of the project:</p>
<div class="language-json codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-json codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"compilerOptions"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"allowJs"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"allowSyntheticDefaultImports"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"downlevelIteration"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"esModuleInterop"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"forceConsistentCasingInFileNames"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"isolatedModules"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"jsx"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"react"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"lib"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token string" style="color:rgb(195, 232, 141)">"dom"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token string" style="color:rgb(195, 232, 141)">"dom.iterable"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token string" style="color:rgb(195, 232, 141)">"esnext"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"module"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"esnext"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"moduleResolution"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"node"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"noEmit"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"noFallthroughCasesInSwitch"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"noImplicitAny"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"noImplicitReturns"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"noImplicitThis"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"noUnusedLocals"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"noUnusedParameters"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"removeComments"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"resolveJsonModule"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"skipLibCheck"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"sourceMap"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"strict"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"target"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"esnext"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">"typeRoots"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token string" style="color:rgb(195, 232, 141)">"./node_modules/@types"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token string" style="color:rgb(195, 232, 141)">"./src/**/*.d.ts"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"exclude"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"build"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"node_modules"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"**/*.spec.ts"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"**/*.spec.tsx"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"include"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"src/**/*"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>This is the <code>tsconfig.json</code> in the <code>.storybook</code> folder:</p>
<div class="language-json codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-json codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"extends"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">"../tsconfig.json"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">"include"</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"../src/**/*"</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">"./storybookTheme.ts"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>Add <code>react.d.ts</code> typings file in <code>src/types/@storybook</code> folder:</p>
<div class="language-tsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-tsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> addDecorator</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">any</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> addParameters</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">any</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> configure</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">any</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> forceReRender</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">any</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> getStorybook</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">any</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> raw</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">any</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> setAddon</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">any</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> storiesOf</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">any</span><br></span></code></pre></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="notes-with-markdown">Notes with Markdown<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#notes-with-markdown" class="hash-link" aria-label="Direct link to Notes with Markdown" title="Direct link to Notes with Markdown">​</a></h2>
<p>For the <code>Storybook Notes</code> we will need <code>raw-loader</code> and <code>@storybook/addon-notes</code> NPM packages:</p>
<div class="language-bash codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-bash codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">yarn add -D raw-loader @storybook/addon-notes</span><br></span></code></pre></div></div>
<p>Register the addon in <code>.storybook/addons.js</code>:</p>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@storybook/addon-notes/register'</span><br></span></code></pre></div></div>
<p>Next, suppose you have a <code>Button.stories.tsx</code> file. Place a <code>notes.md</code> file next to it:</p>
<p><strong>DocsPage</strong> is a new Storybook way of generating documentation (see the <strong>Docs</strong> tab).
However, we can also add extra <strong>Notes</strong> here in plain <strong>Markdown</strong>.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="lo-and-behold">Lo and behold!<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#lo-and-behold" class="hash-link" aria-label="Direct link to Lo and behold!" title="Direct link to Lo and behold!">​</a></h3>
<div class="language-js codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-js codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token console class-name" style="color:rgb(255, 203, 107)">console</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">log</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'Hello world!'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:rgb(130, 170, 255)">bs</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token parameter"> arg </span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword control-flow" style="font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">arg </span><span class="token operator" style="color:rgb(137, 221, 255)">===</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token keyword control-flow" style="font-style:italic">return</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>Add <code>raw-loader</code> to the <code>.storybook/webpack.config.js</code> configuration:</p>
<div class="language-js codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-js codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token literal-property property">module</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">rules</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token literal-property property">test</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex">md</span><span class="token regex regex-source language-regex anchor function" style="color:rgb(130, 170, 255)">$</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token literal-property property">use</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'raw-loader'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><br></span></code></pre></div></div>
<p>Now, in <code>Button.stories.tsx</code> add this code:</p>
<div class="language-tsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-tsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here your imports, etc.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> notes </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">require</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'!!raw-loader!./notes.md'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">default</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add more const if necessary</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">storiesOf</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'Button'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> module</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here your decorators</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">add</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token string" style="color:rgb(195, 232, 141)">'default'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here component details</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      notes</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token maybe-class-name">Information</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'This page can be used for the general audience'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token string-property property">'Design Notes'</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> notes</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<p>Now, if your start your storybook with <code>yarn start</code>, you will see by the <code>Button</code> component the <code>Notes</code> panel with two tabs:</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="information">Information<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#information" class="hash-link" aria-label="Direct link to Information" title="Direct link to Information">​</a></h3>
<p><img decoding="async" loading="lazy" alt="notes panel with two tabs - information tab" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAApMAAADiCAIAAACdldvnAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAACTZSURBVHhe7d0LXBVl4v/xadPF/KmZ6JqkgualNcuVFAXlouIlL6isohii5aXN1bUstey6rbdKy1XS8lL/NdLVXFREREQF7xIes1UCtAQvYOUtsZK09f/MzDPnzOFyBG8x8nm/eMXMPHOeeeZy+M7znDl219WrVxUAAGARv5O/AQCAFZDcAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDVzDkcNfix85AwC/NZIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALCS6/j/c9viFqblymlFqd6sW3iQl5ypuLKTlydm5csZuzvv4BxcFRZky1YUr5ciVj7fwnlhzcjkSWNbymUubZlY+2v/06NC5Gx5p/8zLE2aPqjPAsBvq4x9bpHa5tgW8rMSFy5PFn/LUZR6cOJscuaOkj1jZ6ycLCMR87WTUuQMAKDMypLcol+ppbboSY7WdWtWXS3Iz9pNdmsch8Z+cHLT7szsPjp19BY5CQC4jcowWi5HyT3ajO7tLRfpo8R59cxjwk6D6Y7hYvuru1XLNMaVjar0MtPQcuFNlVCn4FTi3LTbSo6WO7Wt6H4ITsPqhRtsLnSuqrzspzFarjGGx4sbLY8dPWVqjJx2DK2vWeQz8qi2TBManLqws/htWtl5yL3Yzd12jJYDKFdK3+fOvqBFioeHU2Z4BYWPLilghPysROceZ26a6ePg3DR9nN3bw0P8Nz8vW/6NtuVqdchNlVxn4ZLctHI2Nq3vmJKbK1slGmzafa3Bjk8aChWK3TTKyt9+1vRSg/j80jGrDugLnKRHBThiW8ieEe1TYge90MrnlwZNmbhGm3SKbUEUvR11UM4AQIVV+uQ+e9EUOSXQI1d0CU2jxfkXTH987ePJRqGe1s7RrddSvVlLPbhLrNO4l9CL2jiHZPlQq5rWXp0tTs9f2WC9xcYnDdnJmeZCWXZQ3ZvyuJ8BE7zV27V0W7SesiYHZsctTRe/RRd5eurp6anJ2poxSWoe9xslZ5VGr4gi0eFes1NduYX3IjErfhY3EmUp72o3BEfOqQdGFkVEavcK2zaqVQNARXZzvxXm3VvNlt7e2cnLFzr3Lg0ezfUOupdXPVOmOUW3DO56XnpPvuQ6vWpoVYgeqBCnaOv9ZsPI12aMJLQxmujdUrsP0fdavzEyblfkXut7Uy73s8mAl1+qKX6njFzk/Kha+va158Uvr5d6y5HtlgMiQtXfKfHFdLtj47XB83TbqNpTfMSPPpaefi5H/LfJffrNgVoUkO6/TY12xwPtAFBRlT65nbqPJdDSVSg2tF1yRHeh4HZVp3dvvQOq0nOtvD3mXnSgonq1WnLKHskq2a8uXvncz1bPtwlUfx+NnntOW+DE80FHxHo2VzO+LM4dO6hGvn5zoDKiXQ6kA0AFVvrkNnp+hYZpbXGiHygX2Q7q6aqP68qR7VIyovtgrlqFI7hd1ym7po4COcBcThTzbED+xbNyyimuTSFenPK5n53f0Qa3s2OOFr2NyPnaMaydk6n2wl0JDVaHyh0/8km0Vs9Pkku0DQlyIB0AKrAyjJZ764O7xmNlKtEfVj+6lYtkEMkR3+zsPHsulYZefX6umtymHreLOtWbBkG7b/AKCnf6DLw8sMXp4wQyuI3H1ezfEpM3JfrO6kMa9kCWIw3acS3H+9mvg/bxs1kL/75qRzl7Rpx8muzgqmjtAbTAnupj5AatV60oIT21SI5J01c+MPttdcw8QI1n87T6Abke3vpAOgBUYGX7N9REnhQ3EG58ganwM9AaWSjLRNdZ/4RWVmX+7pO9dvNCV3UW1xzza2+jEo6MYN/j4ldytLeYPZWvLUf7WfQLYI4nwO0Lt0ws+m+tGF8Ac3pivIX3om0ttgdEa0+0OQQunv5OP/HbZT23Ed8KA1CulO0JNfU7YPLhZoNIEPvXwrx7O0az1eX6A9LyifFrM55ac/S4BVd1Ojqgkki63yLOSqQO8ZseJVMPn1ODndrr3btIoXxtud5P4wE0k87vnJ7+immh10sRjrg1f3qtajF2m/7cuGTEtiDqCdY+Spec6gGAiqpsfW6gAqLPDaBcubnfCgMAALcWyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAICVkNwAAFgJyQ0AgJXwL7EAAGAl9LkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAAr4VthFZFP7SlyqoJJPT1dTgGAZd11OOuInESFMcR3iZyqYJbtHiGnAMCyGC0HAMBKGC0HAMBK6HMDAGAlJDcAAFZCcgMAYCUkNwAAVkJyAwBgJSQ3AABWQnIDAGAlJDcAAFZCcgMAYCUkNwAAVkJyAwBgJSQ3AABWQnIDAGAlJDcAAFZCcgMAYCUkNwAAVkJyAwBgJSQ3AABWctfVq1fl5LUcmP32qBnnldDg1IWd5SIXDq4KC7Jla5NeL0WsfL6FNvkbiB09ZXvP6e/0k9NTY5TS7kI5kp28PDErX87YVW/WLTzIS85cJ1vcwrRcRfFoM7q3t1x0ExjtdWqhXFj6Vou25Xrc1HYBwB3gFvW506PGyNgWPB/8rWI7PSpAi+o7VH5W4sI4m5wpl/KzDl5n+0TMa7cUAIBCbu1oeeDi6amnZX+3PAhZqLbHah1uB9FdHW3o1qy6uig37cay27u3Vtst69jeaPsAAIVc72i5HAyvGZncJicoKUVbQY6Km8bJNY1eOT0qRJ3YMrG2XFNRXzhpbEt9Wi4PDG2UEnNUzIu8949X+8qiwojMaL3TrFcuh7sLj8CLvnX00nQ5YwyGmzcnqM1Qio6Wr1nkM1LdqKqF96JtA1rp03J5o1eS74s2dkc07De6Cyl+oLnoSLdconJe12m43VxUpA7HmmK15hcTHaX2VbtVyzQqK2GUvdjNFbcTpgabCsxLBWMjJe6d8wtKaBMA3CFusM99fqkR20L2jOiJa+R0YSLOnXJUvHBKoZX12Bah7tlE+61VaB/rzp4RF2Ya+jZtyzm2hZiksNnm+RKJexFHbAvptlG1F8XKGd3Rqaa7kJSRb0cdlNPlgbeHh/orN1fr1YpgNOedaSjdKUcFUbQ82XRvZWKLc6wpVjPnpyE3zVRZblpJNamqV1fHBfKzdhe7TqEGm1tcVMl7VzjnRZvK+WcIAHBDbni0XPRfT09PPR0cqM2lxG9RWg5YeToiUusPa6PlosNtfOwtOrXqytMXvVRTXXmkc0zKUntfXBAdZXvl57PTzbNKztdaPB9M3yZ+GzW/Eqouy848pSid3yncDGcHV02bcV78Ft13bRf0lY9OHb1FK5ZkabK31sE7v21jqe4JbpNa1bQRc43toJqnoi+qjX6PbqOGem6mFplnL6pJK4v0Ufb8vOxiwjQ7OVOLQNFrdaxahFNFJdQk1Wuub62Yj7uzk3drNwBGi/Xq9MF1795G7VpL1P5+yXuXfUG7j5Bt1kqMmxkAuBPdYHLXjPybPuzc2V+LzOLp4SpWni/Hols930ZL36PbTd3uwAnGSLVd6INa3BqVF5rVqTcK01O3DWi1ZpFP7TI8j3Zg4zf6zcTLctS9xdgJjdTfMV+b7icaReilLVsE6GuVV7ZcLXPVvqhG74XmXzwr/qsHvF60PNsrXE0481iznRHxLfXBZq+g5loOOvNorr/Uy6ueFq4u1QryNSWySXZ2nr4tX9kQY2PFhq6rvfOqoTVD9LSFOOUWf24PAL+5W/uEmrP7Gjo60/d7liIIvZrfL6c0hWYNWybWniIy22ncu/QequW4XWhyXzFpVp7pSetK/gVxe+Il41NbIMOvuPFk2Xs1MXfqr5M9kTMPXtQWOKlew3HIy74xbe9ED13vaKv0/F7oaggfACzudib3uWOOD4lP5dykUecDs9O0j89rRiY7RsvLIOPsATmlKEfOWevvvTFO7OHoYMoxYzvZtfYK0jraghFycqj5Gq59a1AKMlnzc3OLVqZnr+7aGyth74wH5B3j+9f/bTQAKPduS3LLoebzS8es0mPSiNtG/jf8qHZOpvpZtRLaRvt0fMv24kbL5Sfizlp1b6z+2U+3TZOPs6VHvav12uWYfLlnPEymB7fxtJoMZPWBLqPvaZ5WQ04Pb32o2Ykc/7bHnvGx9w3zbmnv8xvs2zKeXrN/xm66D7Enu4u9Ux9QU2mDCOIOxfj43XRLAAB3lNvT5zY+QlYf3lZHttVvl6kPjhV5aqzsPJurD7spMUnqgLnT4+sO2TOifWoXeSy85YAI/XE2tVS8Vn9AvdEr5fjb3vbPeVX6Z70ebeRHujId5Soy1LWPpOV4daEPiZ0TUmcf2dbHnBPzlMKBe53M4/WSsS2jWbLFxu5IWqlI6JL3zthx2WZZVr2el94dB4A7zu0aLe83yv5MuEYd3L4p341u9fwkxwh5aLB8CFw+ZdZi7Hz9mfDiqf8wy2LtlkKnPqB+E24mbht18NgRdI7+pk6UGoX2jrakPqNd/DNc3r0ddXi0CW9uqu/GGEFtoo5xm5vl1KrCWe9i7woXqWXFPoAHAHeEu0r/L7Hgjpctv/gtMlSLPjlvzAIAygGSGyZGdDshuAGgPLmdz5aj3Csy8ExsA0B5Q58bAAAroc8NAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYyV0Nd8+Wk7jFctpPkFMAAFwvkvv22ezeV04BAHC9GC0HAMBK+P9zAwBgJfS5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5AQCwEpIbAAArIbkBALASkhsAACshuQEAsBKSGwAAKyG5UWGtm+zTya/En8j5B5TYiWLi5Vi5fiEH5od18gtbcEDOwuFAVKR+AC1CvRLCo4ptboHt4wmhQV3VSyI0yiYXXp+CnK0Lxs7cIOdiXxZ1Ti7h2rrDaNdDSe+jm0c9pPKqc/nOvROQ3Kiw/vBw18Au8qdNo2qKUs2znWmJ571yPVRcBRs+XbD/zH2+I1/82wujO3jKpdcnY/2ClbYzV+QccANIblRY7SKnvfEP+RPRobai1G433LHkb7285HolaDVm5dZdK59pJWdxJ8rIy1UUjy5/fiq0f2iP1u5yKcq7kHe27kqdFiLn7kAkN3ANv6R+Ojm8V6BPJ7+AkGGvrsko0Bc7jZZfyljzekT/4A6d/Hy6BvcY8fqqgxe15YXpA3op2+aPG9hZVhhzyLFqQUbMzFF/DlGLfDoFBvU3bU7I27Z4yhPayG3nPhPUSkQDJq6ThUr+oVVvDgvuoY7rimonfrwtTxYUJVo7bcRg2dq+Y6bFZFySJeomhvXQdlZsJThifNQ2EV2qAwvCfTpNjsmIeXVEjwD9haINJW9DUX7NXfO6dtwCgwaPj0rOceyIcvFgzOsR+m726BExZUlJ9ZjGPyWnJXnboiYMMnZ50LgFW03bcLkJ9YXaGHjX4PCZiSVsXB3jHbUyR1Fylj4rNqGPbItqSzh02vUw8dPYV9Uz2zn4xZUnZIFm3WSfZ6OzFSXlXXtVql8+j544XKtNNPLNGNPJvpSTPH9csRsqyuWFUZCzVe6seiJGTXVcUfogdox66WoHqkOv0HELzJdNicdQvxg+Wfd6H3Hwe/R4/jOxr9pFFaFdG2pVvZ13p2QlX3LFfIrhvCRPvI+0Q9Sh1xNTE41XqQqNlpd8MPUKtxnXg2jAiNfNh1q8I6eOKfboiaOzSr4X1FdNXmxv9u1w9xtvvCEngYrr288/S/hSebj3wLb3yyWqzE3/2pGTl7bliJtv/8j+Pg/kf7Vne8qun/442K++00vOrHt5+Jwdv2vaZ9Dgnl2bVsvZlxAbl3lvrx4PV5UV2WVuWbLtaPberf/9tW3EMyHeNU6mxm9cu/Oy958fE9vNXT5p+Kw9vzwQOGhkr87enlW+y0pL3bb12wYDghpXUgpsUc9N/ijjapMuT4zs3OzSgVX/b+uRX34p8PAd0a25opyJf/XJKUuP3tO+b0R4F5+GV9IT1/8n9nCdrl2aV5dbtrtkWzDyLx+lnruv/eBBYYGN/3dkT9L6Lcce6Nal6d0733568ifZ1XxChoR3CXz4/gs5+207th2q5Bsiepvfpv1n3aHsL7ft/rFx/ydC/ZsrJ/Z9vj3paI1+3Yvu5bepq9cfyMvc+fkZzx7DhwU0+SVrc9z6hGN1Hw9uKtY9E/9mxKQVX1d9bMCw0G7t6l85lLzmsw1ZdYO6Fm2rerguPBrS33FWTEsORP31uaW5dQN7hw8Uu3wpfdOmtcn5j4S3f+AamyhIeiPy5VUnf/9or6eGdWx8YdfiVZlXzp5XWvUY4GM++UrlylUfqHc503ayqn/EX4cEtW75x7rZC0aP+Tj1x7rdIof27dBAO3Trtxc80tOnXiX9ekj/Mu3H1hF/7d7Mo0mHrs1NffTfVXG/9+eML483fPyFkT1FVZ7fix05npe67bBbm7Ane/k+cDF9997NO2X7lQMfjRw1d0e+R3BERF/tikpcszZFbqgQ1xfGgSVPjZ+17WL97gOG9w98qPrxzzfE/yf551a926otVk/TsYOb9/7YtPfgcL/md5207dy9+Wi1kJ4trnGatIvhq/22H9sOerpPE4/mfsE1kp6LeH9Xwf2dh4gGP9q4yvdfpe7fuvmU56AAce1qG7q346guokHOClxdckpW0qLdPzidF9OSgs1vDngz5njlR0KHPhHkmZ/yScxXl8+dVfRrQ3vnNpBbdHUw1Qq/Obpvy5Hfdwgf0rdNze8yvkjdtPenRwf6ird4wf75T074YPcPtfz6R4T7NfnfNzsTN23SL+MzG14f/ManR+7xCRsU9vhjDa9kJsXExmW5d+5W9CK+Na4CuPrF+wODfAfO/0LOSmtfCPJtGzx2Wa6cv7rn3T5BvqFR+9Rp00vWTvFt+8RcbanqUsqMx7t3fzn2vJw3UdcMCgifv++SXHBy2XMBbYPHrzh99Wrmv8b06eTUBm1z+pKsj4a3Der+QuxJveTqpX3zhge0DfJ9IVad2/NeP9HOpdk/a2Wq3H+P9QvqN2uPnHU4vXJssK/fc8vt+3Rp59t9unefsPL41aQZPXuKTYimSKc/G+9nbOKL+YPF5gZG2Vv+89opogGT1spZsy/mDRW72e+tnUZ7Lu14K8y37dD31T1RdypgTHS2UY9o6/Ixwb593tsrZ03Uw6W/yuBYoh3/Z1fbd/nk0rEBgU/NTxOTLjdR9EjOUVs7eJ55MwZtr42irMVDg3w7TfqP49BlfyKq9ZuwUj1kWnvajv3EXlqYtoJ+MAX9Shjzb6MZV/fOEodIv4q0c9TnrZR8vUTQDqDckDOXF8bpFRMC2obNSL6glwk/75glLhXtepOnafAcm/00rX0h2LftFO2UujyG+sUwKtre+Mx/Pdfd3+lMabsjl2gb0qstxOUldzV2UuHz4liStWiUb9s+k9Yah/uSba56/OUWtXeuvkXXB1Ot0Omcms64dvTMb3/1hZ26TF5xXNs7v+c+MR0d7Y0c9m7RN9ytwWg54Jp3p9B6clJp96C4hz+e6zQOKtStU1c5uf6DOXFpp9SRb7eAF+MTEqb2KeERt0rtBz/l7SZnPEI7ta98Zf/+VEVpFvl+7BanD861zV38SdR5dEdqplKrS78+HrLIzXtU3zZyWrHtSftWqXufYouPWR2j/+y+WOVe5du9NvNQoyb1C9uVyn6d+tn3yc1vYmxCwuyB9ZUuL65fn/BOH0dP0b1pM9EB/OmnM3JeadDBz97yKp71RWOOHSuyBalp7/5+VeS0W4fggAbK8V27Dym2tD2nlPvvU/atN5oas+dilRrKKVtaSTUVr36dupWU1BX/+GRH5hl1BNNj6LyU5CXPPCYOh6tNnEn7b+EjGdFLvOjasnfvyVDce/R1XA5ungNC/Ktdtm1LNI6QV4tH7KWl0KZLP6MZik/TJopy8oS4tgq279l75R6PKqcT7e2P//bXe5XLtrSdcmU7lxdGQcpu2+WqdaucSTLqWS0qqqlcSf18l1xFecDPv7X9NHl6itYfPyFORClOk+ejLe2Nbxb5bsK2pWNM1662Oz/+WPyHRnbXvuRKcGbf/sNK7cCQEONwu7Ue0r+1nDYrzcFs5dvTftZa1W+oKDk5x8Tk3v1fXq7s09V0vjtMWrElaWZY/f17d32n3H+vsi/eqHP1nou/r6F8l/p52S7i60ZyA65VqmRkVYnaDXompP4vX6ydPia8W0DIoBEzP0oq4XNuVT1PT1ONbg09H1Auf51tvOPzTx1NS4pZ/dGsN8ZFhMxJUZTTZ8VfsXMX8hWlyYP2rBbcGj1oPEN34sRJ8Uc/ad7cWTPtP9E7T4tleaLAyaETOZcVD8+Gxh/rIgrOHDu4Y33MsvlTXxzVd8qKbEX5/qz9TuV3d5f+L0adOk3llMq7oWjsd6dOKSdyj4twSFxsaurcj7afVZS8k4Xb6pp7nyeHelc/vXXeq08+3ju4x4jJUTF79M+5XW7ixBlxXDwbPKTVoXOvXaeanHTlBzWGvBo4jfhWub+OSJ3TZwrfy5VS8deW9ljcz7bV5vbPWn1YlJzMPaSvYufywsg4JQ7pT/9daa5n5oZMUXLylFHR7+6+W045ua7TdPHUN58nrY5ZMufVv47oMUvcHJw9fa0EVrm85Epw4uz3itKovtNp/IN7MaexNAez0t3FvR0OHc+5ojxQ3/xmNZw4oR6d5PnmOhftFfuae/I2fdhNcgM3rl63Vz6J3/Dem0/3fazh3WcyNi6eMm7AxHVleBNXqlRJvO03zhwcEBI6aOJrsxfHbD1yqW7ntsZfpp8LfpZTJfJ7MXXrrkI/O9/sKUsNV678KqeKKrB9PL535wGDn3p12px/J+z+vkpbv0dry7Kbwq3qPfqE/ytFmpq6aVrhtl5DFe/IqISYpe+Oi+jW1P3Kye1L500Y8pf5NvkEUVk2cc89Jd7I/GY8I+cUaf/W6L88LIsN174wvMIWFKln17JRhSsqThmOYV7itIE9uoWMGD9l/vzPdmRdqtOtnfnGrSQ39ZKrUqWke+xSHkxnV351/Q2+wAmFKhQ/KTMel6W3GMkN3BxV3P8UPOLZedGrkzYuGt+h6oWU+ETReyjGmdOi12dXcCznpFKtWeOHCxI/fGvjsfsff3NZ7K6d6+PWRy+aPbS18biLR50/KMqRr9PkrEp7oc69Ti3RucgsMpRajFZejSsruTnHzA8qx7/UI/jPc3ccXjZvwZe//Omp+RsSdm2LjV2/ZN4rnRrKVa7D2bPm3bcdE3P316mnuNcSndT0DPto7TU5Ha5DuYVuh6o36Rg6Zur8FUlr183p53k5e03sDtebqO8ukiHneIacVZ05fsx8Rkpy7/+JLl32cbXLanfp1Peip+XhYe773bD6tdQmfpVRmv6qywujfq06osWHvypNRYWU7TQVJC745/qcP4RMW5SYuikpYdWKJTOHeZdiHKMUl5zz6VcHETTarh094XQaj50sZkfLcjCdtfJ6sJJy8oT5OxFK/GudgyLm7HCvLSo9lFWaN9wtQnIDN8q2YHSPgNFL1BE4TbUG9eq46MT9tCNujZE/BemfxO+5XNXXt6OS8XXWRaVBh67BTWRcX8pJ2PmFPqk06ujTXDm7eY2jH58bs3XPZTndIdC/rnJ20yp7taIPtOb5zl2Dx6tf13Hm8yfvSpd3bV1j//JP3prNewsuN27U5qsjIpQe6RL2J3fZdbmYsmNXaSKteBkb1+437g/yYpdvPK40bd+xkdKhY+f7lTMJa2Mc3z7Ki3muV2DQROevUWn+r2o15aejR40jW7B/yxbjduCHda/16NXjtURjE27ujWrX1CddbsLd97FHK5uPVYFtecKXctolL9/2DzlXW5CzKnb7xcoPt7Z/+H9TuAcHtKukfL5+mTF+oDbyn5F+AYPn7JDzdi4vDPeugd6Vlf1ro+0nQrlkez/cp0foe0UqKqRMp0nJOJLxk9KgXbeuTWRcF+Rs2PFffdKVa1xyVcW90sVvjtlPvy1p+zdy2r1d+4crn94SY29fwf4V64rbYlkOZiHtWj9a+XLqJschyIvZtO/SZc/Gbf0Cu/xBMW9dPeyTu3Xo9dyK6/zcpKyKfMUAQBl5+7WtHb1s6bjROb2D/uShnLJtjk08W6PLyD4l/FsuF3e+P3pYRmjf5sr+mOiNJ+4JnPB0dzeloNkfaygJK98ce2Vg50b3nE/fFJt4+MLdlRT9r3DTISMHbZqyYu7oYYfkC7ec0go07QY9GbhlZso/IwZ+GRH+iFvul5vjdmQU1I8YFlJfrmHn3ufJ0LW2lXOHjvg6vPcf3XK2RK+3FXgNi+hTpeq5hyvv2j1n5OvnQlvd9/Op3Ykxu0797/qHkaufW/fS8BN9+/hWyV4bm/jVz40jn3lCHUBtN2ik38apu2YNGnpgWGgrt1NfbEpM+eqXBpFDirZV6di+Y42khI9fe/5Snw41f9i7du2Byl7uijbef69f+9aLkhLeHX4mvVsXz5rncpLi1ovSYf27iEKXmxgwOjzpuaVOp8C4BXKt6RPPhm0dt3LW0BFfqYfulGjP9hylceSIAdf4R3t0NcRtiLIv/p3oK+3b9/eXC4slz9HycYMzQ8XFUJC9eUvc5ydqBE4I6yjXcHB5Ybj3jRi05svoTycNyOgV3tWz4JvtibH7j9Xwe3Fw0YoKcXmaCndgH2rWoroSv+a1Zy6LrdxzLnPDmuSsH+6urFzrH4z7Y3OXl1xHv4DqCfHLXnruUn//e3/YvWHV/kqNa+unX2kUNmLQhknRs8c8lR7Su4VyYPmKTTnFbq4sB9OZdvQmRb/39LCv+/dt4Zaz6bM1+35p/FRYiLjNGBLhv+Hd7TOfHLx/UFhrt1O25Pithws8w4b2K3oR3xL0uYEb1mrUB++NbF/7+13LF82auWjFjh+bR77+4RuPO56YdeY/bqLvr7uiZ8791/bLj4g1p2oPBrt1mRQ1vmujX9NXiEo+XLm/SuCk96KebKKOhe5Vizs8P/sfkY/8Pmfz4plzo7+oM2D68PZabZp6Ie98OHO0b4Nzu0Tp+8tTv6vtP+HDuWOK6wtW8X5m8ZLxvTx/3PrR3FlzE47U9n9hyQdPtxIZEPn36WFt7zub/OHcWbM/jc9rPHz2hy92rqqcPJJ1HcOtyiOj3x5SNytu4cyliTn3th83/YOx8hlmj5BpH70T6d/wh+1iQ3Njdn1bK2jSe/ZSJ/KY/Lh/6aJZCzeceugvc17wMQZh3Xu+Me/VsMZXMxPELs/6MOGb/1N3Wd2Ra2zCzXvs3PmT/N1PJqtHcvfv/V98wlddfm3i0H3w4Tjj0MXs+6XFwL/PW1xsy4vRqNug7o3+d2T13LkfJhV+0KwQeY4ecsuIERfD0rjMq47rpDCXF4Zb6zEfz3shpOnvv1r//sy5i2OPXG0VNm3Ja/Ynsl0ow2lS3IJfevuF7g2vHForthK1/GDVoHHzPxjSTFGyDqvXbomuccnJai/uW/n+zKWxeU3HRv3Nzz4GL3Zt4XsTOtfKTVw6a+aKvW5+L4z0kUXOynIwncmjVz8/aZl4X687XCvoxXmL/6JdYfX6vPXJ30cEPnA+RWxdvOW/d+88bv7CZ27u4IsLd129elVOArjVYl/2m7rL/5Wtb934P8xYsOZ5/3+eeOLdFeOL+zIMKiwujAqAPjdgBZun9Qjq//d4x9Myuet3/1ep5NWohZxHxcSFUSGR3IAVdGzvV+n8xpkjJ0cti4lZ/dHU0aNnpxY0CR3U/XYNz6F84sKokBgtB26jGxgtv5ST/NGsxbEHTl64pFSuWrdZcNizz4Y+XIqv3uDOxoVRAZHcAABYCaPlAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAICVkNwAAFgJyQ0AgJWQ3AAAWAnJDQCAlZDcAABYCckNAIB1KMr/B3eUMFfMj5kEAAAAAElFTkSuQmCC" width="659" height="226" class="img_y867"></p>
<p>and</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="design-notes">Design Notes<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#design-notes" class="hash-link" aria-label="Direct link to Design Notes" title="Direct link to Design Notes">​</a></h3>
<p><img decoding="async" loading="lazy" alt="notes panel with two tabs - design notes tab" src="https://madrus.dev/assets/images/notes-panel-with-two-tabs-design-52265f395da9f042dbf6b2fcd8619cc7.png" width="763" height="522" class="img_y867"></p>
<blockquote>
<p>The words <em>Information</em> and <em>Design Notes</em> here are arbitrary. You can use any other words instead. The only exception a.f.a.i.k. is the word <em>markdown</em>, which has a special meaning as a keyword in Storybook. I must say, however, that I have had issues trying to implement <code>Notes</code> with this <em>markdown</em> option. E.g., single quotes would be replaced with <code>&amp;#39;</code> on the screen.</p>
</blockquote>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="docspage-with-mdx">DocsPage with MDX<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#docspage-with-mdx" class="hash-link" aria-label="Direct link to DocsPage with MDX" title="Direct link to DocsPage with MDX">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="pre-requisites">Pre-requisites<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#pre-requisites" class="hash-link" aria-label="Direct link to Pre-requisites" title="Direct link to Pre-requisites">​</a></h3>
<p>For the <code>Storybook DocsPage + MDX</code> we will need <code>@mdx-js/loader</code>, <code>babel-loader</code> and <code>@storybook/addon-docs</code> NPM packages:</p>
<div class="language-bash codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-bash codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">yarn add -D @mdx-js/loader babel-loader @storybook/addon-docs</span><br></span></code></pre></div></div>
<p>Register the addon in <code>.storybook/addons.js</code>:</p>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@storybook/addon-docs/register'</span><br></span></code></pre></div></div>
<p>Add the following configurations to the <code>.storybook/config.js</code> file:</p>
<div class="language-jsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-jsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> </span><span class="token imports maybe-class-name">DocsContainer</span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token imports"> </span><span class="token imports maybe-class-name">DocsPage</span><span class="token imports"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@storybook/addon-docs/blocks'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword module" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token imports"> addDecorator</span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token imports"> addParameters</span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token imports"> configure </span><span class="token imports punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@storybook/react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here other imports</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here your decorators</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">addParameters</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">options</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">sortStoriesByKind</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here other options</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">docs</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">container</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token maybe-class-name">DocsContainer</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">page</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token maybe-class-name">DocsPage</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token function" style="color:rgb(130, 170, 255)">configure</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    require</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'../stories'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex">stories</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex">tsx</span><span class="token regex regex-source language-regex quantifier number" style="color:rgb(247, 140, 108)">?</span><span class="token regex regex-source language-regex anchor function" style="color:rgb(130, 170, 255)">$</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    require</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'../stories'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex">stories</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex">js</span><span class="token regex regex-source language-regex anchor function" style="color:rgb(130, 170, 255)">$</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    require</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">context</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'../stories'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex">stories</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex">mdx</span><span class="token regex regex-source language-regex anchor function" style="color:rgb(130, 170, 255)">$</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  module</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<p>Add the following to the <code>.storybook/presets.js</code> file:</p>
<div class="language-js codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-js codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">'@storybook/addon-docs/react/preset'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><br></span></code></pre></div></div>
<p>And this goes into <code>.storybook/webpack.config.js</code>:</p>
<div class="language-js codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-js codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> createCompiler </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">require</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'@storybook/addon-docs/mdx-compiler-plugin'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here your other const</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">module</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method-variable function-variable method function property-access" style="color:rgb(130, 170, 255)">exports</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token parameter"> config</span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token parameter"> mode </span><span class="token parameter punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain">config</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">resolve</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain">config</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">resolve</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">extensions</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token string" style="color:rgb(195, 232, 141)">'.js'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'.jsx'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'.ts'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'.tsx'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'md'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'mdx'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here your other settings</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token literal-property property">module</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">rules</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// add here other extensions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token literal-property property">test</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token regex regex-source language-regex">stories</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex">mdx</span><span class="token regex regex-source language-regex anchor function" style="color:rgb(130, 170, 255)">$</span><span class="token regex regex-delimiter">/</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token literal-property property">use</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token literal-property property">loader</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'babel-loader'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token literal-property property">loader</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'@mdx-js/loader'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token literal-property property">options</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">              </span><span class="token literal-property property">compilers</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token function" style="color:rgb(130, 170, 255)">createCompiler</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre></div></div>
<p>Now, let us start experimenting with <code>MDX</code>.</p>
<blockquote>
<p><strong>One important observation though.</strong> The names of the MDX files we wish to see in our Storybook should end with <strong><code>.stories.mdx</code></strong>, not just <code>.mdx</code>.</p>
</blockquote>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="where-the-different-names-go">Where the different names go<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#where-the-different-names-go" class="hash-link" aria-label="Direct link to Where the different names go" title="Direct link to Where the different names go">​</a></h3>
<p>Let us create our first file:</p>
<div class="language-markdown codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-markdown codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">    import { Meta } from '@storybook/addon-docs/blocks'</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token code keyword" style="font-style:italic">    &lt;Meta title='Main|Intro2' /&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token code keyword" style="font-style:italic">    # INTRO3</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token code keyword" style="font-style:italic">    Most of the documentation can be done via the __Docs__ option.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token code keyword" style="font-style:italic">    Yet, in some cases we can add side notes in __Markdown__.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token code keyword" style="font-style:italic">    ```js</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token code keyword" style="font-style:italic">    console.log('this is an Intro page!')</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token code keyword" style="font-style:italic">    const test = ({ arg }) =&gt; {</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token code keyword" style="font-style:italic">      if (true) {</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token code keyword" style="font-style:italic">        return false</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token code keyword" style="font-style:italic">      }</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token code keyword" style="font-style:italic">    }</span><br></span></code></pre></div></div>
<div class="language-typescript codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-typescript codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Here</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(130, 170, 255)">I</span><span class="token plain"> have used </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">intro1</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> the name </span><span class="token keyword" style="font-style:italic">of</span><span class="token plain"> the file</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">intro2</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> the </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">meta</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> tag</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> and </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">intro3</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> the text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"> When we now run </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">yarn start</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> we will notice the following</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token number" style="color:rgb(247, 140, 108)">1.</span><span class="token plain"> we don't see the name </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">intro1</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> anywhere</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> and a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">f</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">k</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">this</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">is</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> expected behavior</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token number" style="color:rgb(247, 140, 108)">1.</span><span class="token plain"> we </span><span class="token keyword" style="font-style:italic">get</span><span class="token plain"> to see the </span><span class="token keyword" style="font-style:italic">new</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">MAIN</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> section </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> the menu tree on the left and </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">Intro2</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> a </span><span class="token keyword" style="font-style:italic">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">menu</span><span class="token plain"> option</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   </span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">main menu </span><span class="token keyword" style="font-style:italic">with</span><span class="token plain"> intro2 option</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">images</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">main_intro2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">png</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token number" style="color:rgb(247, 140, 108)">1.</span><span class="token plain"> finally</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">intro3</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> will be </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> the text </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> expected</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">   </span><span class="token operator" style="color:rgb(137, 221, 255)">!</span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">docs panel </span><span class="token keyword" style="font-style:italic">with</span><span class="token plain"> intro3 </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> the text</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">images</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token plain">docs_intro3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain">png</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token operator" style="color:rgb(137, 221, 255)">&gt;</span><span class="token plain"> Using more </span><span class="token function" style="color:rgb(130, 170, 255)">pipes</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">|</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> the </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">title</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> property </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">&lt;Meta /&gt;</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> tag can be used </span><span class="token keyword" style="font-style:italic">as</span><span class="token plain"> a means to create the complete documentation hierarchy next to the </span><span class="token constant" style="color:rgb(130, 170, 255)">UI</span><span class="token operator" style="color:rgb(137, 221, 255)">-</span><span class="token plain">components themselves</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">### </span><span class="token constant" style="color:rgb(130, 170, 255)">MDX</span><span class="token plain"> file using a React component</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">In the previous section the </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">.mdx</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> file was </span><span class="token keyword" style="font-style:italic">in</span><span class="token plain"> fact a pure </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">.md</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> file</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"> Now</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> us add a second file but </span><span class="token keyword" style="font-style:italic">this</span><span class="token plain"> time </span><span class="token keyword" style="font-style:italic">let</span><span class="token plain"> us add a React component inside</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token plain"> For </span><span class="token keyword" style="font-style:italic">this</span><span class="token plain"> example</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> we will need to install </span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">moment.js</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">package</span><span class="token plain"> to format dates</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token plain">` bash</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">yarn add moment</span><br></span></code></pre></div></div>
<p>and create a simple <code>CommitDate</code> React component in <code>src/components</code> folder:</p>
<div class="language-tsx codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-tsx codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports">moment</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'moment'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">import</span><span class="token plain"> </span><span class="token imports operator" style="color:rgb(137, 221, 255)">*</span><span class="token imports"> </span><span class="token imports keyword module" style="font-style:italic">as</span><span class="token imports"> </span><span class="token imports maybe-class-name">React</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'react'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">interface</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">IDate</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  date</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(130, 170, 255)">string</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token keyword" style="font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> </span><span class="token maybe-class-name">CommitDate</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> date </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token maybe-class-name">IDate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token maybe-class-name">React</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access maybe-class-name">ReactNode</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(255, 203, 107)">console</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">log</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">date</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">const</span><span class="token plain"> formattedDate </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">moment</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">date</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">format</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'LL'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token console class-name" style="color:rgb(255, 203, 107)">console</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">log</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">formattedDate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token keyword" style="font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">      </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">em</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain">formattedDate</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">em</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre></div></div>
<p>Now, we create the changelog page: <code>changelog.stories.mdx</code>.</p>
<div class="language-markdown codeBlockContainer_n5dw theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_ej3j"><pre tabindex="0" class="prism-code language-markdown codeBlock_t0lt thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_L6J2"><span class="token-line" style="color:#bfc7d5"><span class="token plain">import moment from 'moment'</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">import { Meta } from '@storybook/addon-docs/blocks'</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">import { CommitDate } from '../src/Components'</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">Meta</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">title</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">Main|Changelog</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">'</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token title important punctuation" style="color:rgb(199, 146, 234)">#</span><span class="token title important"> Changelog</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token table table-header-row punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-header-row table-header important"> Version    </span><span class="token table table-header-row punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-header-row table-header important"> Date                               </span><span class="token table table-header-row punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-header-row table-header important"> Description       </span><span class="token table table-header-row punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-header-row"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token table table-header-row"></span><span class="token table table-line punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(199, 146, 234)">----------</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(199, 146, 234)">----------------------------------</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(199, 146, 234)">-----------------</span><span class="token table table-line"> </span><span class="token table table-line punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-line"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token table table-line"></span><span class="token table table-data-rows punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-data-rows table-data"> </span><span class="token table table-data-rows table-data bold punctuation" style="color:rgb(199, 146, 234)">__</span><span class="token table table-data-rows table-data bold content">1.2.18</span><span class="token table table-data-rows table-data bold punctuation" style="color:rgb(199, 146, 234)">__</span><span class="token table table-data-rows table-data"> </span><span class="token table table-data-rows punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-data-rows table-data"> &lt;CommitDate date={'2019-09-05'} /&gt; </span><span class="token table table-data-rows punctuation" style="color:rgb(199, 146, 234)">|</span><span class="token table table-data-rows table-data"> ✨ Initial release </span><span class="token table table-data-rows punctuation" style="color:rgb(199, 146, 234)">|</span><br></span></code></pre></div></div>
<p>Let us run the Storybook UI with <code>yarn start</code>. First of all, we will get the second menu option under the <code>MAIN</code> menu section:</p>
<p><img decoding="async" loading="lazy" alt="main menu with changelog and intro2" src="data:image/png;base64,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" width="179" height="77" class="img_y867"></p>
<p>And this will be our <code>Docs</code> part:</p>
<p><img decoding="async" loading="lazy" alt="commit_date_mdx_example" src="data:image/png;base64,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" width="398" height="247" class="img_y867"></p>
<p>As you can see, the <code>Date</code> column gets the formatted commit date:</p>
<p><em><code>September 5, 2019</code></em>.</p>
<p><strong>QED</strong></p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="concluding-notes">Concluding notes<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#concluding-notes" class="hash-link" aria-label="Direct link to Concluding notes" title="Direct link to Concluding notes">​</a></h2>
<p>In my personal experience, adding Typescript - even to a working - project can lead to quite a lot of extra wiring and testing. Storybook projects are not an exception. Most of the code snippets in the documentation are written in ES6 en use not types. Just installing the Typescript related NPM packages and changing the file extensions from <code>.js/.jsx</code> to <code>.ts/.tsx</code> is not the end but only the beginning of the refactoring road.</p>
<p>In this blog post, I have shown the steps that were necessary to get the Storybook DocsPage working with MDX stories and Notes with Markdown files. I would be happy if this information helps you to fix your Storybook project.</p>
<p>By the way, it looks that Storybook is going to replace <code>Notes</code> with <code>DocsPage</code>. E.g., <code>Notes</code> is not mentioned any more in the list of add-ons on the <a href="https://storybook.js.org/addons/" target="_blank" rel="noopener noreferrer">Storybook Add-ons</a> page. Well the <code>Docs</code>!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="references">References<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References">​</a></h2>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="articles-about-the-docspage-and-the-storybook-design-system">Articles about the DocsPage and the Storybook Design System<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#articles-about-the-docspage-and-the-storybook-design-system" class="hash-link" aria-label="Direct link to Articles about the DocsPage and the Storybook Design System" title="Direct link to Articles about the DocsPage and the Storybook Design System">​</a></h3>
<ul>
<li><a href="https://www.learnstorybook.com/design-systems-for-developers/react/en/introduction/" target="_blank" rel="noopener noreferrer">Design Systems for Developers</a></li>
<li><a href="https://medium.com/storybookjs/introducing-storybook-design-system-23fd9b1ac3c0" target="_blank" rel="noopener noreferrer">Introducing Storybook Design System</a></li>
<li><a href="https://medium.com/storybookjs/storybook-docspage-e185bc3622bf" target="_blank" rel="noopener noreferrer">Storybook DocsPage</a></li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="sources">Sources<a href="https://madrus.dev/blog/storybook-setup-docspages-and-mdx#sources" class="hash-link" aria-label="Direct link to Sources" title="Direct link to Sources">​</a></h3>
<ul>
<li><a href="https://storybook-design-system.netlify.com/?path=/docs/design-system-intro--page" target="_blank" rel="noopener noreferrer">Storybook Design System</a> and its <a href="https://github.com/storybookjs/design-system" target="_blank" rel="noopener noreferrer">Github repo</a></li>
<li><a href="https://github.com/storybookjs/storybook/projects/3" target="_blank" rel="noopener noreferrer">Storybook Roadmap</a></li>
</ul>
<hr>]]></content>
        <author>
            <name>Andre Roussakoff</name>
            <uri>https://github.com/madrus</uri>
        </author>
        <category label="DocsPage" term="DocsPage"/>
        <category label="Markdown" term="Markdown"/>
        <category label="MDX" term="MDX"/>
        <category label="React" term="React"/>
        <category label="Storybook" term="Storybook"/>
        <category label="Typescript" term="Typescript"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Webdings... Web What?]]></title>
        <id>https://madrus.dev/blog/web-what</id>
        <link href="https://madrus.dev/blog/web-what"/>
        <updated>2016-01-02T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[TL;DR In this blog post, I share my personal story of how I discovered web development and came to passionately love it. Also about my mistakes and misconceptions along the way. It is not about the "ultimate truth" but rather about my personal observations and conclusions.]]></summary>
        <content type="html"><![CDATA[<p><strong>TL;DR</strong> In this blog post, I share my personal story of how I discovered <strong>web development</strong> and came to passionately love it. Also about my mistakes and misconceptions along the way. It is not about the "ultimate truth" but rather about my personal observations and conclusions.</p>
<p>So, it will probably be more interesting to you if you are now in a similar situation to the one I was in at the beginning of the way. It was a long way and it took me at least a year to come to realize what web development was all about. I will be very happy if my story helps you to shorten yours. <!-- -->😃</p>
<p>And, of course, your comments are more than welcome.</p>
<hr>
<p>Hello, Reader. My name is André Roussakoff. At the moment of writing this post, I am 57 and I have never in my life had a blog of my own. I have never realized that it would be so hard to begin. There is so much to say and I have yet no clear understanding of what my blog will finally look like. Only that I have to start.</p>
<p>Oh yeah, about <strong>webdings</strong>. Check my <a href="https://madrus.dev/docs">About</a> page.</p>
<p>I have been a backend application developer for many years developing backend applications with SQL databases. Working mostly with .NET and C#. I had no clear notion of the existence of web development as profession. Websites fascinated me by their beauty and style. Creating websites I called <strong>web design</strong> and I thought that it had everything to do with creative art and Photoshop skills. Being an application developer, I had a feeling that it lay outside of my profession.</p>
<p>Until several years ago. Then one day I was confronted with the necessity to create a website for a good acquaintance of mine.  Somebody mentioned CMS as a tool to create websites and I started my research about CMS. Of course, the most popular were <strong>WordPress</strong> and <strong>Joomla</strong>. Unfortunately, both packages were written in PHP and I was in no hurry to learn another programming language even before I have created my first website. I must admit that I failed at the latter anyway because just using the standard menu options, I was never quite satisfied with the results.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="separation-of-concerns">Separation of Concerns<a href="https://madrus.dev/blog/web-what#separation-of-concerns" class="hash-link" aria-label="Direct link to Separation of Concerns" title="Direct link to Separation of Concerns">​</a></h2>
<p>However, that CMS research on the positive side gave me the notion of <strong>separation of concerns</strong>. That when thinking about a website, one has to consider these four notions:</p>
<ul>
<li><strong>Form</strong> (structure and presentation)</li>
<li><strong>Style</strong> (CSS)</li>
<li><strong>Content</strong> (information)</li>
<li><strong>Behavior</strong> (UX)</li>
</ul>
<p>and that these can be treated rather independently of each other. That was a breakthrough because I suddenly saw a bridge to the world of OOP (Object Oriented Programming), which was very familiar to me and that one does not have to do all at once.
With it also came the realization that my understanding of the notion of web design covered but a small piece of the whole story. That in terms of activities related to the website creation, we can distinguish (at least) the following three:</p>
<ul>
<li><strong>web design</strong></li>
<li><strong>web development</strong></li>
<li><strong>content management</strong></li>
</ul>
<p>Web design has indeed a lot to do with artistic creativity. Web development has to do with tons and tons of programming. And content management is the main responsibility of the actual website owner.</p>
<p>At this point, I decided to look deeper into web development. To my utter amazement the deeper I looked, the more there was to learn and the more confusing it all seemed. In Holland, we have a saying: <em>"Because of all the trees, one does not see the forest"</em>. <!-- -->😃<!-- --> That was definitely true to say about me at that moment. Even now to some extent, I must admit, although I begin to have my preferences.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="web-development">Web Development<a href="https://madrus.dev/blog/web-what#web-development" class="hash-link" aria-label="Direct link to Web Development" title="Direct link to Web Development">​</a></h2>
<p>Zooming further in on web development, I discovered there were two major areas of it:</p>
<ul>
<li><strong>front-end or client side development</strong></li>
<li><strong>back-end or server side development</strong></li>
</ul>
<p>and those developers who are doing both often talk about their work as</p>
<ul>
<li><strong>full stack website development</strong></li>
</ul>
<p>Front-end development has more to do with the visible to visitors part of the website, like menus, animations, complex UX tricks, DOM manipulations, etc.</p>
<p>Back-end development has more to do with the "invisible" activities, like user authentication and authorization, HTTP requests handling, data and database manipulation.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="websites-vs-xxx-apps">Websites vs XXX Apps<a href="https://madrus.dev/blog/web-what#websites-vs-xxx-apps" class="hash-link" aria-label="Direct link to Websites vs XXX Apps" title="Direct link to Websites vs XXX Apps">​</a></h2>
<p>The next "tree" was the realization that mobile devices like smartphones and tablets often require a special approach and that apps we download for an app store are not the websites we browse on our PC or notebook screen. One can distinguish roughly four types of apps:</p>
<ul>
<li><strong>web apps</strong></li>
<li><strong>native apps</strong></li>
<li><strong>mobile apps</strong></li>
<li><strong>hybrid apps</strong></li>
</ul>
<p>A <em>web app</em> is, in fact, nothing more than a classic website, which we view on a mobile device using any installed browser.</p>
<p>A <em>native app</em> needs first to be registered within an app store like Windows Store, Apple Store or Google Play. Only after that we can download it and install on our mobile device. Thus, a native app is not a website but an application.</p>
<p>A <em>mobile app</em> is a web app that has such look and feel that, when started, it is practically undistinguishable from a native app.</p>
<p>Finally, a <em>hybrid app</em> combines the features of both worlds, web and native, and can access the mobile device's hardware. E.g. imagine an app in an app store, which is a wrapper around a classic website. Or a cross-browser app, which is customized to work on mobile devices independent of its platform.</p>
<p>One special sort of apps is a <strong>SPA</strong> (Single Page Application). A SPA has look and feel of a website or a native app with many pages and menu et al. Whereas technically it is all the time one and the same page object, only its elements are in-place replaced by new elements depending on the user action. E.g. the next image replaces the previous image or the content of another page replaces the content of the current page. And due to caching this can happen even without communication between the client and the server.</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="different-platforms">Different Platforms<a href="https://madrus.dev/blog/web-what#different-platforms" class="hash-link" aria-label="Direct link to Different Platforms" title="Direct link to Different Platforms">​</a></h2>
<p>The next "tree" came as a shock. Being a .NET developer I was supposed to "hate" all things Java because all Java developers "hate" all things .NET. <!-- -->😃<!-- --> Also, being a Windows developer I was supposed to "hate" all things Android or macOS. Same reason. All this was quite difficult to digest. Yet, maybe 90% of all mobile devices in the world are not on Windows platform. Have I landed in the wrong camp without even noticing it? The obvious answer seems to be "yes", isn't it?</p>
<p>On the other hand, one can ask another question: should I switch camps at the age of 57? Would it be reasonable and feasible? Fortunately for me, Microsoft seems to also have realized this gap and the hard choice that many a Windows developer was facing because of its previous policy.</p>
<p>As of last year, Microsoft came up with a number of new tools. It went open source with ASP.NET 5 (a.k.a. ASP.NET Core), MVC 6 and Entity Framework 7. It became partners with Cordova for the possibility of cross-platform development under Windows. And it brought out a wonderful light-weight code editor, Visual Studio Code (<strong>VSCode</strong>), which is absolutely NOT a clone of Visual Studio but rather a brother of such editors as Atom, Brackets or Sublime Text and even works on Linux and macOS.</p>
<p>At the same time, I have found out that I can run some traditional Linux/macOS tools under Windows like Nodejs.</p>
<p>As a developer, having all these tools at my disposal,  I don't feel in any way limited by Windows platform as to the kind of web development I can do, now or in future.</p>
<p>Yippee! I don't have to switch the platform! <!-- -->😃</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="javascript-the-language-of-the-web">JavaScript, the Language of the Web<a href="https://madrus.dev/blog/web-what#javascript-the-language-of-the-web" class="hash-link" aria-label="Direct link to JavaScript, the Language of the Web" title="Direct link to JavaScript, the Language of the Web">​</a></h2>
<p>Turning around, the next "tree" was JavaScript. JavaScript for me started at the very early stage of CMS research when my web world consisted of WordPress and Joomla. As soon as I saw some basic <strong>jQuery</strong> scripting, I almost immediately came across this advice (in my free interpretation):</p>
<blockquote>
<p>Avoid using jQuery or JavaScript as much as possible, because inadequate code can completely ruin the website performance.</p>
</blockquote>
<p>At first, it sounded reasonable and for some time I did indeed avoid anything to do with it. Probably for a non-developer, it is a reasonable thing to do. But for me, the more I saw of JavaScript here and there, the more I came to love it and the more wonderful things I saw it can make rather than break. So, I learned myself some JavaScript.</p>
<p>And with that, I perceived a whole new world previously completely unknown to me. I am talking about myriad of different JavaScript frameworks and libraries, like <strong>Nodejs</strong>, <strong>Angular</strong>, <strong>Aurelia</strong>, <strong>React</strong>, <strong>Backbone</strong>, <strong>Underscore</strong> and <strong>Lodash</strong>, <strong>Express</strong> and <strong>Hapi</strong>, <strong>Gulp</strong>, <strong>Grunt</strong>, <strong>Ionic</strong>, <strong>Signalr</strong>, <strong>Karma</strong>, <strong>Jasmine</strong>, <strong>Mocha</strong>, <strong>Selenium</strong> - you name it. Even the names themselves are beautiful to say nothing of what these tools are capable of!</p>
<p>The most important discovery was that it is practically unthinkable to do web development without HEAVY use of JavaScript. Talking about that advice to avoid it as much as possible! <!-- -->😃</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="mvc-and-rest-api">MVC and REST API<a href="https://madrus.dev/blog/web-what#mvc-and-rest-api" class="hash-link" aria-label="Direct link to MVC and REST API" title="Direct link to MVC and REST API">​</a></h2>
<p>In this final part of the article, I want to talk about the concept of <strong>separation of concerns</strong> that I have mentioned earlier and in a very different context. When talking about CMS, this separation was related to Form, Style, Content and Behavior. Now, I realize that on a lower, more technical level this "external" separation of concerns can be hard coupled with the beautiful <strong>MVC</strong> (Model-View-Controller) paradigm. MVC relates to the way we structure our code in terms of responsibilities and it determines the division between:</p>
<ul>
<li><strong>Model</strong> (representation of the data structure)</li>
<li><strong>View</strong> (the way to present the information to the user)</li>
<li><strong>Controller</strong> (application logic behind the scenes which binds Views and Models together)</li>
</ul>
<p><strong>On the client side</strong>, everything can be written in plain JavaScript but it is probably much easier to use some specialized JavaScript framework of library. My impression is that at the moment, the most popular framework for client side development seems to be <strong>Angular</strong> with <strong>React</strong> only a half step behind, although my personal beauty prize goes to <strong>Aurelia</strong>.</p>
<p><strong>Angular</strong> has also such advantage that, in combination with <strong>Ionic</strong> framework, it makes it easier to create cross-platform apps. And as to <strong>React</strong>, it is the Facebook's main development tool.</p>
<p>In the earlier versions of ASP.NET MVC, Microsoft used out-of-the-box no JavaScript for client side development. The clients had to send AJAX requests to the server. The response was composed on the server and after that sent to the client. With the corresponding performance penalty. On the other hand, the standard tool for the development of views is <strong>Razor</strong>. This fantastic tool makes it possible to combine HTML code with C# snippets, so that we can manipulate HTML tags based on C# variables and use conditional logic and loops. Recently, I came across a wonderful <strong>Umbraco</strong> CMS, which became my second love in the world of web development, the first being <strong>Aurelia</strong>. Umbraco CMS is free, is based on ASP.NET MVC 4, and it uses Angular on the client side.</p>
<p><strong>On the server side</strong>, I have discovered the wonderful world of <strong>RESTful API</strong>. Simply explained, it is a two-way translation between the URL string composition and the corresponding action that has to be executed. Here is a couple of trivial examples how a <strong>REST API</strong> could look like:</p>
<ul>
<li><a href="http://website.com/" target="_blank" rel="noopener noreferrer">http://website.com</a>  - show home page</li>
<li><a href="http://website.com/articles" target="_blank" rel="noopener noreferrer">http://website.com/articles</a>  - show list of articles</li>
<li><a href="http://website.com/articles/1" target="_blank" rel="noopener noreferrer">http://website.com/articles/1</a>  - show or update article with id = 1</li>
</ul>
<p><strong>REST API</strong> can be implemented in a lot of different ways: with <em>JavaScript</em> (e.g. Nodejs + Express) or with <em>C#/ASP.NET</em>.</p>
<p>Also, it is now possible to develop with JavaScript inside the Visual Studio 2015, or alternatively develop completely outside of Visual Studio using VSCode on any platform, Windows, Linux or macOS, and even run natively C# code on all of them using OmniSharp!</p>
<h2 class="anchor anchorWithHideOnScrollNavbar_wY3a" id="round-up">Round up<a href="https://madrus.dev/blog/web-what#round-up" class="hash-link" aria-label="Direct link to Round up" title="Direct link to Round up">​</a></h2>
<p>Surprisingly, it has become quite a big article, over 2000 words. I have told you about the different steps I had gone through before I had discovered the "forest" of web development as my new love. Although there are so many different puzzle pieces in the web development picture, there some important binding concepts that keep it all together and give me the feeling of beauty.</p>
<ul>
<li>the most important central notion of <strong>separation of concerns</strong> (both in CMS and MVC)</li>
<li>the possibility to use <strong>same toolset</strong> for different aims (different apps and SPAs), so everything become more accessible and understandable</li>
<li><strong>Microsoft going open source</strong> with the latest release of ASP.NET, MVC and Entity Framework and its support for traditional Linux/macOS tooling as well, so no necessity to switch to Java camp</li>
<li><strong>huge open source community</strong> behind all of this, which made it possible for me to come this far and maybe even inspired me to write this article</li>
</ul>
<p>This is by far not the end of the way! It is only the first step. From complete illiteracy to learning to read and understand something of what I have read. A much more difficult step is the next one: learning to write. Meaning developing complete projects from A to Z and thus using the tools I have learned.</p>
<p>I believe I have yet to add a link here and there in case somebody becomes interested to go into more details on some tool or framework, although Google search also can help.</p>
<p>Thank you, the Reader, for coming this far. If there is anything at all that you could add as feedback on this article, please do. Be it positive or negative. I will accept it thankfully.</p>
<hr>]]></content>
        <author>
            <name>Andre Roussakoff</name>
            <uri>https://github.com/madrus</uri>
        </author>
        <category label="history" term="history"/>
        <category label="overview" term="overview"/>
        <category label="about" term="about"/>
    </entry>
</feed>