<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Omar Hussein</title>
    <description>The latest articles on DEV Community by Omar Hussein (@omalk98).</description>
    <link>https://dev.to/omalk98</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1155056%2F3c21bd79-028f-4b18-bdfc-447268c5ea5d.png</url>
      <title>DEV Community: Omar Hussein</title>
      <link>https://dev.to/omalk98</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omalk98"/>
    <language>en</language>
    <item>
      <title>Finalizing my Vue.js Context Menu</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Mon, 11 Dec 2023 06:42:43 +0000</pubDate>
      <link>https://dev.to/omalk98/finalizing-my-vuejs-context-menu-pmp</link>
      <guid>https://dev.to/omalk98/finalizing-my-vuejs-context-menu-pmp</guid>
      <description>&lt;p&gt;In the previous posts, we discussed laying the foundation, overcoming challenges, and leveraging Vue slots for flexibility and reusability. Now, let's explore the latest advancements, including the integration of built-in keyboard shortcuts and ensuring compatibility with the project's dark theme.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advancements and Integrations:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Reusing the Action Component:&lt;br&gt;
To enhance the user experience and streamline interactions, I reused the action component provided by the FileBrowser project. This component comes equipped with built-in keyboard shortcuts for fundamental actions like delete, move, and copy, providing a consistent and familiar experience for users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keyboard Shortcuts for Efficiency:&lt;br&gt;
Not much was needed to be done in terms of keyboard shortcuts. The project already has these features built-in and adding the context-menu allowed for enhanced productivity and making the browser interface even more user-friendly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dark Theme Compatibility:&lt;br&gt;
Considering the diverse preferences of users, ensuring compatibility with the dark theme was important. I made sure the styling of the context menu seamlessly integrated with the project's dark theme. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Looking Ahead:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Potential Vue.js Upgrade:&lt;br&gt;
As the Vue.js ecosystem evolves, it's essential to consider future upgrades. While contemplating a move from Vue 2 to Vue 3, early assessments indicate that the transition might be relatively smooth. Vue 3 introduces powerful features and optimizations, and fortunately, the changes required for our context menu seem minimal. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ongoing Refinement:&lt;br&gt;
The journey doesn't end here. Continuous refinement is key to adapting to evolving user needs and maintaining a high-quality user experience. Future steps include addressing user feedback, exploring additional features, and staying aligned with the project's overall development roadmap.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;From the initial design considerations to the integration of keyboard shortcuts and dark theme compatibility, every step aimed at elevating the user interface and making interactions with FileBrowser seem more natural and consistent with other file browsers. I look forward to future enhancements, potential upgrades, and the continual evolution of this essential feature in the FileBrowser project.&lt;/p&gt;

&lt;p&gt;If you have any questions, feedback, or suggestions, feel free to reach out or open an issue with the &lt;a href="https://github.com/filebrowser/filebrowser/issues"&gt;FileBrowser&lt;/a&gt; project. I've been really enjoying working on this project and I regularly check for issues I can address!&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Enhancing my Vue.js Context Menu component</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Mon, 11 Dec 2023 06:09:41 +0000</pubDate>
      <link>https://dev.to/omalk98/enhancing-my-vuejs-context-menu-component-jcb</link>
      <guid>https://dev.to/omalk98/enhancing-my-vuejs-context-menu-component-jcb</guid>
      <description>&lt;p&gt;In my previous blog post, I wrote about implementing a custom context menu in Vue.js for the FileBrowser project. I covered the initial steps, from understanding project requirements to creating a basic structure for our context menu component. Now, let's dive into the progress made, overcoming challenges, and refining the approach for a more flexible and reusable solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Progress and Challenges:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Basic Logic and Right-Click Functionality:&lt;br&gt;
The initial focus was on establishing the fundamental logic to handle the menu popup triggered by a right-click event. This involved capturing the right-click event and toggling the visibility of our context menu. This step lays the foundation for a responsive and interactive user experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating the Menu - A Stylish Twist:&lt;br&gt;
One challenge was deciding how to construct the menu itself. After some exploration, I found that customizing the style of the existing action component within the context menu was the optimal solution. Doing so helps with the overall design and consistency of the project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Separation of Concerns with Vue Slots:&lt;br&gt;
To keep the codebase clean and maintainable, we can make use of Vue slots. This approach allows for better separation of concerns, enabling encapsulation of the menu's structure and behavior within the component while providing users the flexibility to customize the content through slots, allowing future developers to tailor the context menu to specific needs in different areas of the application.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Vue Slot Advantage:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Flexibility:&lt;br&gt;
Vue slots allow developers to inject content into predefined areas of a component. This flexibility is essential for the context menu, as it allows users to seamlessly add custom options, icons, or other elements without modifying the core functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reusability:&lt;br&gt;
By using Vue slots, the context menu becomes inherently more reusable. Whether it's within the FileBrowser project or another Vue.js application, the context menu can adapt to various requirements without sacrificing its core functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintainability:&lt;br&gt;
Separating concerns using Vue slots contributes to the maintainability of our code. Developers can easily comprehend and modify specific aspects of the context menu without disrupting its overall behavior. This modularity is key for ongoing development and future enhancements.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;With the foundation laid and initial challenges conquered, our next steps will involve expanding the range of context menu options, refining the styling further, and conducting more extensive testing. In the upcoming blog post, I'll detail the evolution of the context menu and enhancing its capabilities.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Implementing a Custom Context Menu in Vue.js</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Mon, 04 Dec 2023 04:00:25 +0000</pubDate>
      <link>https://dev.to/omalk98/implementing-a-custom-context-menu-in-vuejs-43ib</link>
      <guid>https://dev.to/omalk98/implementing-a-custom-context-menu-in-vuejs-43ib</guid>
      <description>&lt;p&gt;Crafting a user-friendly interface is a constant task that requires ongoing refinement. As part of a project I've been recently enjoying working on, I decided to enhance FileBrowser with a new user-interface feature by introducing a custom context menu. This addition aims to empower users with quick access to relevant actions and streamlining their interaction with the application and making feel a lot more like a real file browser you would get on a desktop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task Overview:
&lt;/h2&gt;

&lt;p&gt;My goal is to create a custom context menu that dynamically appears in the bottom right corner of the screen upon a user's right-click. This context menu will not only cater to the specific needs of the FileBrowser project but will also intelligently adjust its position to stay within the viewport.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing for the Feature Addition:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Understanding FileBrowser Requirements:
&lt;/h3&gt;

&lt;p&gt;Start by thoroughly understanding the FileBrowser project's current structure and user interface. Identify areas where a context menu would provide valuable functionality, such as file management actions or navigation shortcuts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Custom Vue Component:
&lt;/h3&gt;

&lt;p&gt;Design a Vue component responsible for the custom context menu. This component should encapsulate the menu's structure, styling, and behavior. Utilize the template, script, and style sections to keep your code organized.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining Context Menu Options:
&lt;/h3&gt;

&lt;p&gt;Identify the specific actions the context menu should offer. These should map directly to the operations that are available in the header menu of FileBrowser to make access to these operations easier. Each option should have a label, possibly an icon, and a corresponding callback function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Dynamic Positioning Logic:
&lt;/h3&gt;

&lt;p&gt;Implement logic to dynamically calculate the context menu's position. Account for factors such as window dimensions, menu dimensions, and cursor coordinates. This ensures the menu remains visible and accessible within the user's viewport.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration with Golang Backend:
&lt;/h3&gt;

&lt;p&gt;If required, establish communication between the Vue.js frontend and the Golang backend of FileBrowser. Define API endpoints for backend interactions triggered by context menu actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thorough Testing:
&lt;/h3&gt;

&lt;p&gt;Rigorously test the custom context menu component across various scenarios. Verify its responsiveness, correct positioning, and the proper execution of each menu option. Conduct integration tests to ensure seamless communication with the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation and Code Comments:
&lt;/h3&gt;

&lt;p&gt;Document the Vue component and describe how to use it, customize it, and the integration with the FileBrowser backend. Include clear code comments to aid future developers in understanding and maintaining the context menu functionality.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>vue</category>
      <category>programming</category>
    </item>
    <item>
      <title>Breaking Language Barriers: Contributing to FileBrowser's Arabic Localization</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Mon, 27 Nov 2023 21:39:04 +0000</pubDate>
      <link>https://dev.to/omalk98/breaking-language-barriers-contributing-to-filebrowsers-arabic-localization-45j6</link>
      <guid>https://dev.to/omalk98/breaking-language-barriers-contributing-to-filebrowsers-arabic-localization-45j6</guid>
      <description>&lt;p&gt;Recently, I found myself drawn to &lt;a href="https://github.com/filebrowser/filebrowser"&gt;FileBrowser&lt;/a&gt;, a web file browser built with Golang and Vue.js, and I decided to make my first contribution. However, my approach was a bit unconventional—I didn't dive into the code immediately. Instead, I leveraged my proficiency in Arabic to enhance the project's Arabic translation file. In this blog post, I'll share my experience of breaking language barriers and contributing to FileBrowser through non-code means.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project: FileBrowser
&lt;/h2&gt;

&lt;p&gt;FileBrowser is a versatile web file browser that seamlessly integrates Golang's backend strength with Vue.js's frontend agility. Its user-friendly interface and robust features make it a popular choice for those seeking an open-source file management solution. Recognizing the global nature of open-source projects, the FileBrowser team actively encourages contributions from users around the world, including efforts to improve language translations.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Contribution: Arabic Translation Refinement
&lt;/h2&gt;

&lt;p&gt;As a native Arabic speaker, I found an opportunity to contribute to FileBrowser that aligned with my linguistic strengths. I refining the Arabic translation file for the project, aiming to make the user interface more accessible and user-friendly for Arabic-speaking users.&lt;/p&gt;

&lt;h3&gt;
  
  
  In my initial contribution, I focused on:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Language Accuracy:&lt;/strong&gt; Ensuring that the translated text accurately conveyed the intended meaning in Arabic, maintaining clarity and coherence.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; Aligning terminology and phrasing throughout the interface to create a consistent and seamless user experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cultural Sensitivity:&lt;/strong&gt; Adapting expressions and text to be culturally appropriate, addressing the nuances of the Arabic language with its regional variations and dialects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The process involved a meticulous review of the existing translation strings, making adjustments for linguistic precision and cultural context. My goal was to enhance the overall usability of FileBrowser for Arabic-speaking users.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Impact:
&lt;/h2&gt;

&lt;p&gt;While my contribution may not involve lines of code, it has an impact on the accessibility and inclusivity of FileBrowser. A well-crafted translation ensures that users, regardless of their language preference, can navigate and utilize the application effectively. In the case of Arabic-speaking users, this means a more seamless and natural experience, fostering a stronger connection with the software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Plans:
&lt;/h2&gt;

&lt;p&gt;My initial contribution to FileBrowser through language translation is just the beginning. I am excited about the potential for further collaboration with the project. Future plans include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ongoing Refinement:&lt;/strong&gt; Continuously refining and updating the Arabic translation to accommodate changes in the project and user feedback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Contributions:&lt;/strong&gt; Actively participating in adding features to FileBrowser and contributing to the growth of the project.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Contributing to open-source projects goes beyond writing code. My experience with FileBrowser showcases that leveraging non-code skills, such as language proficiency, can have a meaningful impact on the project's accessibility and user experience.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>go</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Empowering Caddy: User Friendliness with Case-Insensitive Caddyfiles</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Sat, 25 Nov 2023 06:39:18 +0000</pubDate>
      <link>https://dev.to/omalk98/empowering-caddy-user-friendliness-with-case-insensitive-caddyfiles-4hil</link>
      <guid>https://dev.to/omalk98/empowering-caddy-user-friendliness-with-case-insensitive-caddyfiles-4hil</guid>
      <description>&lt;p&gt;An interesting project that I recently contributed to is Caddy, a fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS, written in the language I'm currently exploring, Golang. My contribution and &lt;a href="https://github.com/caddyserver/caddy/pull/5919"&gt;pull request&lt;/a&gt; address case-insensitive support to special prefixes in the Caddyfile, along with the ability to recognize files with a '.caddyfile' suffix, all inspired by a reported issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Issue:
&lt;/h2&gt;

&lt;p&gt;Issue &lt;a href="https://github.com/caddyserver/caddy/issues/5909"&gt;#5909&lt;/a&gt; on the Caddy GitHub repository sheds light on a limitation that Caddy encountered when handling Caddyfiles with specific prefixes. The issue reported that Caddy failed to recognize files with the 'caddyfile' suffix and did not handle these files in a case-insensitive manner. This presented a hurdle for users attempting to configure Caddy with files having different casing or using the '.caddyfile' suffix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Contribution:
&lt;/h2&gt;

&lt;p&gt;The recent contribution to Caddy addresses the reported issue by introducing two key features:&lt;/p&gt;

&lt;h3&gt;
  
  
  Case-Insensitive Support for Special Prefix Case Caddyfile:
&lt;/h3&gt;

&lt;p&gt;With this enhancement, Caddy now supports special prefixes in the Caddyfile in a case-insensitive manner. This means that users can employ different casings for these prefixes without affecting the configuration, providing a more flexible and user-friendly experience.&lt;/p&gt;

&lt;h4&gt;
  
  
  Support for '.caddyfile' Suffix, Also Case Insensitive:
&lt;/h4&gt;

&lt;p&gt;Another notable addition is the support for the '.caddyfile' suffix. Caddy can now recognize and handle files with this suffix seamlessly. Moreover, the recognition process is performed without being case-sensitive, ensuring a consistent and intuitive user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handles Extension Check Without Case Sensitivity:
&lt;/h3&gt;

&lt;p&gt;The contribution also addresses the broader issue of handling file extensions without case sensitivity. This ensures that Caddy can accurately identify and process Caddyfiles, regardless of the casing used in the file names.&lt;/p&gt;

&lt;p&gt;These improvements not only resolve the reported issue but also enhance the overall usability of Caddy, making it more adaptive to diverse user preferences and naming conventions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reasons to Contribute:
&lt;/h2&gt;

&lt;p&gt;The pull request associated with this contribution aligns with the core principles of open-source collaboration, offering several compelling reasons to merge the changes into the Caddy codebase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Enhanced User Flexibility: Case-insensitive support for special prefixes and '.caddyfile' suffix empowers users to configure Caddy with greater flexibility, accommodating various naming conventions and preferences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Improved File Recognition: Caddy's ability to recognize and handle files in a case-insensitive manner contributes to a smoother user experience, preventing potential configuration errors due to case discrepancies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Community-Driven Progress: This contribution reflects the collaborative spirit of the open-source community, where users actively participate in refining and expanding the capabilities of the tools they rely on.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Contributing to Caddy provided me with a hands-on opportunity to apply and reinforce my newfound golang skills. This recent enhancement not only resolves a specific issue but also contributes to the continual improvement of Caddy as a versatile and user-friendly web server. As you explore the world of open-source development, remember that every contribution, big or small, plays a vital role in shaping the future of the projects we depend on.&lt;/p&gt;

</description>
      <category>go</category>
      <category>opensource</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Automating Releases with GitHub Actions</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Sat, 25 Nov 2023 06:29:50 +0000</pubDate>
      <link>https://dev.to/omalk98/automating-releases-with-github-actions-50kn</link>
      <guid>https://dev.to/omalk98/automating-releases-with-github-actions-50kn</guid>
      <description>&lt;p&gt;Developing a static site generator (SSG) Command Line Interface (CLI) tool called &lt;a href="https://github.com/omalk98/TILvert"&gt;TILvert&lt;/a&gt; was a fun experience. As I wrapped up the final lines of code, the next logical step was to share it with the world. This led me to publish &lt;strong&gt;TILvert&lt;/strong&gt; to &lt;strong&gt;NPM&lt;/strong&gt;, and in this blog post, I'll share the process, highlighting how I automated the release using GitHub Actions. You can find the npm package &lt;a href="https://www.npmjs.com/package/tilvert"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Preparing for NPM Publication
&lt;/h2&gt;

&lt;p&gt;Before diving into the automation magic, I needed to make sure &lt;strong&gt;TILvert&lt;/strong&gt; was polished and ready for public consumption. This involved thorough testing and ensuring that my package was not only functional but also user-friendly.&lt;/p&gt;

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

&lt;p&gt;I reached out to friends and colleagues to act as beta testers, providing them with early versions of TILvert. Their feedback proved invaluable in identifying and fixing bugs, improving the user interface, and refining the overall user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Obtaining an NPM Access Token
&lt;/h2&gt;

&lt;p&gt;To publish a package to NPM, you need to authenticate yourself. NPM provides access tokens for this purpose. Here’s how you can obtain one:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Visit the NPM website:&lt;/strong&gt;&lt;br&gt;
Go to the &lt;a href="https://www.npmjs.com/"&gt;NPM website&lt;/a&gt; and sign in or create an account if you haven’t already.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Tokens:&lt;/strong&gt;&lt;br&gt;
Navigate to your account settings, and under the "Tokens" tab, generate a new token. Remember to give it the necessary permissions for publishing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep it Secret:&lt;/strong&gt;&lt;br&gt;
Treat your access token like a password. Never share it publicly, and keep it secure.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: Integrating GitHub Actions for Automation
&lt;/h2&gt;

&lt;p&gt;With TILvert ready and the NPM access token in hand, the next step was to automate the release process using GitHub Actions. This would ensure a seamless and consistent deployment every time a new version was ready.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the GitHub Actions Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a &lt;code&gt;.github/workflows&lt;/code&gt; directory:&lt;/strong&gt;&lt;br&gt;
Inside your project, create a directory named &lt;code&gt;.github/workflows&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Workflow YAML file:&lt;/strong&gt;&lt;br&gt;
Create a YAML file within this directory, for example, &lt;code&gt;release.yml&lt;/code&gt;. This file defines the workflow.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Release&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;master"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TOKEN }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pnpm/action-setup@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;20.x"&lt;/span&gt;
          &lt;span class="na"&gt;registry-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://registry.npmjs.org"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pnpm install --no-frozen-lockfile&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pnpm run lint&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Format&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pnpm run prettier&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pnpm run test&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pnpm run build&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create release branch&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config user.email "77292466+omalk98@users.noreply.github.com"&lt;/span&gt;
          &lt;span class="s"&gt;git config user.name "Omar Hussein"&lt;/span&gt;
          &lt;span class="s"&gt;git checkout -b release&lt;/span&gt;
          &lt;span class="s"&gt;git add -f dist/ package.json&lt;/span&gt;
          &lt;span class="s"&gt;git commit -m "Create release branch"&lt;/span&gt;
          &lt;span class="s"&gt;git push origin release --force&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pnpm publish --no-git-checks&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;NODE_AUTH_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NPM_TOKEN }}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This workflow triggers on every push to the main branch, installs dependencies, and publishes the package to NPM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up GitHub Secrets:
&lt;/h3&gt;

&lt;p&gt;In your GitHub repository, go to "Settings" -&amp;gt; "Secrets and variables" -&amp;gt; "actions" and add a secret named NPM_TOKEN with the value being your NPM access token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Documentation and User Instructions
&lt;/h2&gt;

&lt;p&gt;A crucial aspect of a successful release is clear documentation. Ensure that users can easily understand how to install and use TILvert. This is all available in the &lt;code&gt;README.md&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pnpm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; tilvert
&lt;span class="c"&gt;# or using the release branch&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pnpm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; https://github.com/omalk98/TILvert.git#release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Uninstall
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pnpm uninstall &lt;span class="nt"&gt;-g&lt;/span&gt; tilvert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tilvert &lt;span class="o"&gt;[&lt;/span&gt;flags/options] &amp;lt;path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Publishing TILvert to NPM and automating the release with GitHub Actions has been a rewarding process. With each new version, users can benefit from the latest features and improvements without hassle. I hope this guide inspires you to share your creations with the world and streamline your release process. &lt;/p&gt;

</description>
      <category>typescript</category>
      <category>npm</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>Optimizing Excalidraw: Simple File Size Reduction Tactics</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Thu, 23 Nov 2023 15:27:47 +0000</pubDate>
      <link>https://dev.to/omalk98/optimizing-excalidraw-simple-file-size-reduction-tactics-n4e</link>
      <guid>https://dev.to/omalk98/optimizing-excalidraw-simple-file-size-reduction-tactics-n4e</guid>
      <description>&lt;p&gt;Excalidraw is a versatile and user-friendly platform for creating diagrams, sketches, and collaborative drawings. As with any software, users and developers are constantly looking for ways to enhance its performance and efficiency. In this post, I'll explore my recent contribution to Excalidraw that addresses a crucial issue and significantly improves the file size of drawings.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Issue:
&lt;/h2&gt;

&lt;p&gt;Excalidraw users may have encountered a common concern regarding the size of save files, libraries, and the clipboard. Issue #7169 on the Excalidraw GitHub repository highlights the problem, pointing out that even small drawings could result in file sizes as large as 612K. The issue context notes that, upon inspecting the .excalidraw file with a text editor, the JSON structure is "prettified," contributing to the larger file sizes. The user suggests that minifying the .excalidraw files could save substantial space without sacrificing usability.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Contribution:
&lt;/h2&gt;

&lt;p&gt;The proposed solution comes in the form of a modification to the JSON.stringify function, ensuring that the output to the file does not include unnecessary spacing, essentially minifying the JSON. This change results in a notable reduction in file size for save files, libraries, and when copying to the clipboard.&lt;/p&gt;

&lt;p&gt;To put this improvement into perspective, a simple test file exhibited a reduction from &lt;strong&gt;31.4kb&lt;/strong&gt; to &lt;strong&gt;17.1kb&lt;/strong&gt;. User reports indicate that the reduction becomes even more significant as drawings increase in complexity. For instance, the original issue mentioned a file size reduction from 612K to 296K when using the &lt;code&gt;jq -r tostring&lt;/code&gt; command to minify the &lt;code&gt;.excalidraw&lt;/code&gt; file. Notably, the minified file still opens seamlessly in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reasons to Merge:
&lt;/h2&gt;

&lt;p&gt;The pull request containing this modification presents compelling reasons to merge the changes into the Excalidraw codebase:&lt;/p&gt;

&lt;h3&gt;
  
  
  Reduces Size on Local/Cloud Storage:
&lt;/h3&gt;

&lt;p&gt;Minifying the &lt;code&gt;.excalidraw&lt;/code&gt; files leads to a substantial reduction in file size, addressing the concern of large storage requirements. This optimization not only benefits individual users but also contributes to more efficient cloud storage solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Faster Saving on Slow Connections:
&lt;/h3&gt;

&lt;p&gt;The reduced file size directly translates to faster saving, especially for users with slower internet connections. This improvement enhances the overall user experience by minimizing the time required to save and load drawings.&lt;/p&gt;

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

&lt;p&gt;Excalidraw continues to evolve, thanks to the active contributions of its community. The recent &lt;a href="https://github.com/excalidraw/excalidraw/pull/7187"&gt;pull request&lt;/a&gt; to minimize the size of &lt;code&gt;.excalidraw&lt;/code&gt; files is a example of how user feedback and developer expertise come together to enhance the platform's performance. By addressing the issue of inflated file sizes, Excalidraw becomes an even more efficient and user-friendly tool, catering to the diverse needs of its growing user base.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Enhancing TILvert: GitHub Actions CI and Release Workflow</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Fri, 17 Nov 2023 20:38:55 +0000</pubDate>
      <link>https://dev.to/omalk98/enhancing-tilvert-github-actions-ci-and-release-workflow-4gog</link>
      <guid>https://dev.to/omalk98/enhancing-tilvert-github-actions-ci-and-release-workflow-4gog</guid>
      <description>&lt;p&gt;Introduction&lt;/p&gt;

&lt;p&gt;Continuous Integration (CI) has become a crucial aspect of maintaining project quality and stability. In this blog post, I'll share how I went about setting up GitHub Actions CI Workflow for my TypeScript Static Site Generator (SSG) app, &lt;a href="https://github.com/omalk98/TILvert"&gt;TILvert&lt;/a&gt;, and the subsequent release workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up GitHub Actions CI Workflow
&lt;/h2&gt;

&lt;p&gt;To ensure the reliability of TILvert, I decided to implement a CI workflow using GitHub Actions. The &lt;code&gt;main.yml&lt;/code&gt; file in the &lt;code&gt;.github/workflows&lt;/code&gt; directory outlines the steps for linting, testing, and building the project on every pull request to the master branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# main.yml&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;master"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;lint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... (steps for linting)&lt;/span&gt;

  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... (steps for testing)&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... (steps for building)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow includes three jobs: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;linting&lt;/li&gt;
&lt;li&gt;testing&lt;/li&gt;
&lt;li&gt;building &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each job is configured to run on an Ubuntu environment and utilizes the pnpm package manager for dependency management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing with My Partner's Repo
&lt;/h2&gt;

&lt;p&gt;Collaborating on a project with a partner introduced me to different testing setups and CI configurations. While my project uses &lt;code&gt;Vitest&lt;/code&gt; for testing, my partner's repo employed a different testing framework, &lt;code&gt;Jest&lt;/code&gt;. Writing tests for a project I didn't create required understanding their codebase and testing conventions. It was a valuable experience that helped better understand testing practices others prefer to use and encouraged me to adopt a more versatile approach. &lt;a href="https://github.com/sdthaker/Node-TILify/pull/19"&gt;Pull Request&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflection on CI Implementation
&lt;/h2&gt;

&lt;p&gt;Now that I've set up CI for TILvert, I appreciate the seamless integration of GitHub Actions into my workflow. The automatic execution of linting, testing, and building processes on each pull request provides quick feedback, enabling me to catch issues early in the development cycle. CI has become an important part of my development process, boosting my confidence in the project's stability and ensuring a consistent code quality standard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Release Workflow for TILvert
&lt;/h2&gt;

&lt;p&gt;In addition to CI, I implemented a release workflow to automate the process of creating a release branch on the master branch push.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# release.yml&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Release&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;master"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... (steps for linting, testing, building)&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create release branch&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git config user.email "77292466+omalk98@users.noreply.github.com"&lt;/span&gt;
          &lt;span class="s"&gt;git config user.name "Omar Hussein"&lt;/span&gt;
          &lt;span class="s"&gt;git checkout -b release&lt;/span&gt;
          &lt;span class="s"&gt;git add -f dist/ package.json&lt;/span&gt;
          &lt;span class="s"&gt;git commit -m "Create release branch"&lt;/span&gt;
          &lt;span class="s"&gt;git push origin release --force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow, triggered on a master branch push, ensures that the latest changes are thoroughly tested before creating a release branch. The release branch includes the dist/ directory and the package.json file, ready for installation. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/omalk98/TILvert/actions/runs/6908472849"&gt;Successful Run&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional Challenges and Learnings
&lt;/h2&gt;

&lt;p&gt;As an additional challenge, I configured the release workflow to force-push the release branch to the remote repository. This posed some initial challenges related to authentication and permissions, but once resolved, it streamlined the release process. I learned about GitHub Actions secrets and the importance of secure practices in automated workflows.&lt;/p&gt;

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

&lt;p&gt;Integrating CI and release workflows into TILvert has been a rewarding journey. The automated processes have enhanced collaboration, code quality, and overall project reliability. As I continue to iterate on TILvert and explore new features, these workflows will remain integral to maintaining a robust and dependable TypeScript SSG. I encourage fellow developers to delve into GitHub Actions and explore the possibilities it offers for improving their development workflows.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>testing</category>
      <category>githubactions</category>
      <category>vite</category>
    </item>
    <item>
      <title>Enhancing Code Quality: Testing in My TypeScript SSG App</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Wed, 08 Nov 2023 18:58:44 +0000</pubDate>
      <link>https://dev.to/omalk98/enhancing-code-quality-testing-in-my-typescript-ssg-app-37ph</link>
      <guid>https://dev.to/omalk98/enhancing-code-quality-testing-in-my-typescript-ssg-app-37ph</guid>
      <description>&lt;p&gt;Developing a robust, error-free open-source project is a goal every developer wishes to achieve. One of the best ways to ensure the reliability and correctness of your codebase is through testing. As I added testing to my TypeScript Static Site Generator (SSG) app, I encountered challenges, made exciting discoveries, and solidified my belief in the power of testing. &lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the Right Tools: Introducing Vitest
&lt;/h2&gt;

&lt;p&gt;Selecting the appropriate testing framework is very important. After working with Jest for JavaScript and JUnit for Java in the past, I opted for &lt;a href="https://vitest.dev/"&gt;Vitest&lt;/a&gt; for my TypeScript SSG app &lt;a href="https://github.com/omalk98/TILvert"&gt;TILvert&lt;/a&gt;. Vitest is a fast, modern, and efficient testing framework for JavaScript and TypeScript projects. It offers a clean and simple syntax, making it easy to write and understand test cases and since it uses the same syntax as Jest, I felt right at home.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Vitest in My Project: A Step-by-Step Guide
&lt;/h2&gt;

&lt;p&gt;Implementing testing in your project might seem daunting, but with the right guidance, it becomes manageable. Here's a detailed guide on how I set up Vitest in TILvert:&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; vitest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuration:
&lt;/h3&gt;

&lt;p&gt;Although Vitest comes with sane defaults for small projects, you may wish to add some configuration to modify your testing behavior.&lt;/p&gt;

&lt;p&gt;Create a vitest.config.js file in your project directory to configure Vitest. Define your test files and other necessary configurations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example configuration:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/**/*.test.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// Other configuration options...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Writing Test Cases:
&lt;/h3&gt;

&lt;p&gt;Write test cases using Vitest's simple syntax. Ensure thorough coverage of your codebase, testing different functionalities and edge cases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vitest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./my-math.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Test Math Logic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Test Sum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running Tests:
&lt;/h3&gt;

&lt;p&gt;Execute tests using the following command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Alternatively, if you have Vitest installed locally you may run the &lt;code&gt;vitest&lt;/code&gt; command, or if it is included in &lt;code&gt;package.json&lt;/code&gt; and installed, you can add a runner in the &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest --run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test:watch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest --watch"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lessons Learned and Aha Moments
&lt;/h2&gt;

&lt;p&gt;While writing test cases for TILvert, I had several "aha!" moments. I realized that some of my logic was generating incorrect HTML tags in specific scenarios. This discovery not only improved my understanding of the code but also enhanced the overall user experience. Additionally, I encountered minor bugs that had gone unnoticed during the development phase. These bugs, once surfaced by the tests, were promptly fixed, ensuring a smoother user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;As for the future, I am convinced that testing will be a fundamental part of my projects. The assurance it provides in terms of code quality and reliability is unparalleled. I will continue exploring new testing frameworks and tools, ensuring that my open-source projects are of the highest quality and provide an exceptional user experience.&lt;/p&gt;

&lt;p&gt;Integrating testing into TILvert was a challenging yet rewarding experience. It not only improved the app's reliability but also deepened my understanding of the codebase. I encourage fellow developers to embrace testing in their projects, as it is a vital step toward creating robust and dependable software solutions.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>testing</category>
    </item>
    <item>
      <title>Preparing Your TypeScript Project for Consistent Contribution</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Sat, 04 Nov 2023 05:14:59 +0000</pubDate>
      <link>https://dev.to/omalk98/preparing-your-typescript-project-for-consistent-contribution-25g1</link>
      <guid>https://dev.to/omalk98/preparing-your-typescript-project-for-consistent-contribution-25g1</guid>
      <description>&lt;p&gt;Developing a TypeScript project can be exciting, but as your codebase grows, maintaining consistency and quality becomes crucial. To streamline your development process and making sure code integrity remains a priority, integrating tools like ESLint, Prettier, Husky pre-commit hooks, and configuring .vscode extensions.json settings can boost your workflow significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting the Stage: Prettier Formatter
&lt;/h2&gt;

&lt;p&gt;Before diving into the details, let’s assume you’ve already integrated Prettier into your project. Prettier ensures consistent code formatting and can be easily customized to fit your team’s preferences. If you haven’t added it yet, make sure to do so and configure it according to your project’s needs.&lt;br&gt;
Simply install it with pnpm or npm and setup your preferred config in the &lt;code&gt;.prettierrc&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm i prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: ESLint Setup
&lt;/h2&gt;

&lt;p&gt;ESLint is a powerful tool for identifying and fixing common coding issues. To get started, install ESLint and its TypeScript parser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;eslint @typescript-eslint/eslint-plugin eslint-config-standard-with-typescript eslint-plugin-import eslint-plugin-n eslint-plugin-prettier eslint-plugin-promise &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create an ESLint configuration file in your project’s root directory:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Follow the prompts to set up your ESLint configuration. Ensure you select TypeScript as the project type and choose the appropriate options based on your project requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Husky Pre-commit Hooks
&lt;/h2&gt;

&lt;p&gt;Husky allows you to set up Git hooks easily. Git hooks enable you to run scripts before committing changes. To integrate Husky into your project, install it using npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;husky &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
npx husky add .husky/pre-commit &lt;span class="s2"&gt;"npm lint &amp;amp;&amp;amp; npm prettier"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once Husky is installed, add the same pre-commit hook to your package.json file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"husky"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pre-commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run lint &amp;amp;&amp;amp; npm run prettier"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration runs ESLint on staged .js and .ts files, fixes any issues automatically, and stages the changes for commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: .vscode Extensions.json Settings
&lt;/h2&gt;

&lt;p&gt;Visual Studio Code provides a powerful extension system that enhances the editor’s functionality. You can configure these extensions on a per-project basis using .vscode/extensions.json. Create this file in your project’s .vscode directory if it doesn’t exist already.&lt;/p&gt;

&lt;p&gt;Here's an example of .vscode/extensions.json for TypeScript development:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recommendations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"dbaeumer.vscode-eslint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ms-vscode.vscode-typescript-tslint-plugin"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration, I recommend three extensions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;dbaeumer.vscode-eslint: Integrates ESLint into VS Code, highlighting and fixing issues directly within the editor.&lt;/li&gt;
&lt;li&gt;esbenp.prettier-vscode: Provides Prettier integration, ensuring consistent code formatting as you code.&lt;/li&gt;
&lt;li&gt;ms-vscode.vscode-typescript-tslint-plugin: Offers TypeScript and TSLint support, aiding in identifying and fixing linting errors in your TypeScript code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By configuring these extensions, you enhance your development environment and ensure a seamless coding experience.&lt;br&gt;
Wrapping Up&lt;/p&gt;

&lt;p&gt;Integrating ESLint, Prettier, Husky pre-commit hooks, and configuring .vscode extensions.json settings can significantly improve your TypeScript project’s quality, consistency, and overall development experience. By following these steps and customizing the configurations to fit your specific needs, you can optimize your workflow, catch errors early, and collaborate more effectively with your team.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>typescript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Docusaurus: Copying the sitemap feature</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Fri, 03 Nov 2023 04:17:50 +0000</pubDate>
      <link>https://dev.to/omalk98/docusaurus-copying-the-sitemap-feature-2hpg</link>
      <guid>https://dev.to/omalk98/docusaurus-copying-the-sitemap-feature-2hpg</guid>
      <description>&lt;p&gt;In my last post i talked about Docusaurus's sitemap generator feature that enhances the search engine optimization (SEO). By understanding its logic and flow, I successfully implemented a similar functionality tailored to my own application. I will do a quick walkthrough of my implementation, explaining the key decisions made during the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Understanding the Docusaurus Sitemap Generator Logic
&lt;/h2&gt;

&lt;p&gt;Docusaurus's sitemap generator is designed to filter out specific routes based on exclusion criteria, ensuring that only SEO-friendly pages are included. Avoiding the exclusion criteria for now, I replicated this logic in my own implementation, focusing on two essential components:&lt;/p&gt;

&lt;h3&gt;
  
  
  a. Sitemap Construction:
&lt;/h3&gt;

&lt;p&gt;To construct the sitemap, I utilized the popular npm package "sitemap." This package facilitates the creation of a structured sitemap, ensuring that each URL is correctly formatted with trailing slashes and base URLs. The use of the &lt;code&gt;SitemapStream&lt;/code&gt; class enabled seamless construction and formatting of the sitemap content.&lt;/p&gt;

&lt;h3&gt;
  
  
  b. Integration and Usage:
&lt;/h3&gt;

&lt;p&gt;I integrated my custom sitemap generator into my SSG application, similar to how it is seamlessly integrated into Docusaurus. This integration allows the sitemap generation process to be part of my build workflow, ensuring that an up-to-date sitemap is generated each time I update my website content.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Implementation Details
&lt;/h2&gt;

&lt;h3&gt;
  
  
  a. Initialization:
&lt;/h3&gt;

&lt;p&gt;I initiated the sitemap generation process by initializing essential variables and validating the presence of the site's URL in the application configuration. This step ensures that the sitemap contains accurate and relevant URLs.&lt;/p&gt;

&lt;h3&gt;
  
  
  b. Sitemap Generation:
&lt;/h3&gt;

&lt;p&gt;Valid routes, which passed the exclusion checks, were formatted with appropriate trailing slashes and base URLs. These formatted routes were added to the sitemap stream. Once all valid routes were added, the sitemap stream was converted into a string, representing the final structured sitemap content.&lt;/p&gt;

&lt;h3&gt;
  
  
  c. Getting the Routes:
&lt;/h3&gt;

&lt;p&gt;One of the important steps was to get the route links dynamically. To achieve this, I designed a recursive mechanism that reads the output directory of my SSG application. By recursively traversing the directory structure, I gathered a map of all the files and their respective locations within folders. I then passed this information to the sitemap generator function which uses the paths as links. &lt;/p&gt;

&lt;h2&gt;
  
  
  The End
&lt;/h2&gt;

&lt;p&gt;Understanding the inner workings of Docusaurus's sitemap generator gave me with valuable insights into creating SEO-friendly sitemaps for static websites and be able to generate the map dynamically based on the files rather than manually adjusting the map.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>opensource</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Docusaurus: Understanding the sitemap feature</title>
      <dc:creator>Omar Hussein</dc:creator>
      <pubDate>Fri, 03 Nov 2023 01:05:41 +0000</pubDate>
      <link>https://dev.to/omalk98/docusaurus-understanding-the-sitemap-feature-2ige</link>
      <guid>https://dev.to/omalk98/docusaurus-understanding-the-sitemap-feature-2ige</guid>
      <description>&lt;p&gt;Docusaurus, the popular static site generator, simplifies the process of building documentation websites. Among its powerful features is the sitemap generator, a vital component for enhancing a site's search engine optimization (SEO).&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring the Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;isNoIndexMetaRoute&lt;/code&gt; Function:
&lt;/h3&gt;

&lt;p&gt;This function is crucial for determining whether a specific route should be excluded from the sitemap. It checks the HTML head of a page for a meta tag with the name "robots" and the content "noindex". If found, the route is excluded from the sitemap. This ensures that pages marked as 'noindex' in their meta tags are not included in the generated sitemap.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;createSitemap&lt;/code&gt; Function:
&lt;/h3&gt;

&lt;p&gt;Input Parameters: The function takes several parameters, including siteConfig (Docusaurus configuration), routesPaths (an array of route paths), head (HTML head content for each route), and options (plugin options for the sitemap).&lt;/p&gt;

&lt;p&gt;Exclusion Logic: The function filters out routes that should not be included in the sitemap. Routes ending with &lt;code&gt;404.html&lt;/code&gt; are excluded, as are routes matching patterns specified in &lt;code&gt;ignorePatterns&lt;/code&gt; from the options. Additionally, routes with 'noindex' meta tags, identified by &lt;code&gt;isNoIndexMetaRoute&lt;/code&gt;, are excluded.&lt;/p&gt;

&lt;p&gt;Sitemap Construction: This process uses a popular npm package by the obvious name of &lt;strong&gt;sitemap&lt;/strong&gt;. The included routes are formatted with appropriate trailing slashes and base URLs. The function constructs a sitemap using the SitemapStream class and writes the formatted routes into the sitemap.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Integration and Usage:
&lt;/h3&gt;

&lt;p&gt;This sitemap generator function is typically integrated into Docusaurus build processes or plugins. It generates a structured sitemap for the entire documentation website, improving its discoverability by search engines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Flow
&lt;/h2&gt;

&lt;p&gt;Initialization: The function begins by initializing necessary variables and checking if the site's URL is provided in the configuration. If not, an error is thrown to ensure the URL is properly set.&lt;/p&gt;

&lt;p&gt;Exclusion Checks: The function checks each route for exclusion criteria. If a route matches any exclusion condition (404 page, ignore patterns, or 'noindex' meta tag), it is skipped from the sitemap generation process.&lt;/p&gt;

&lt;p&gt;Sitemap Generation: Valid routes are formatted, including trailing slashes and base URLs, and added to the sitemap stream. The sitemap stream is then converted to a string and returned as the final output.&lt;/p&gt;

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

&lt;p&gt;Understanding the inner workings of the Docusaurus sitemap generator gives valuable insights into how SEO-friendly sitemaps are created for static websites. By examining the logic and flow of the code, this helps me understand how to integrate this logic into my own SSG application, which I will talk about in my next post!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>opensource</category>
      <category>documentation</category>
    </item>
  </channel>
</rss>
