<?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: Renan Franca</title>
    <description>The latest articles on DEV Community by Renan Franca (@renanfranca).</description>
    <link>https://dev.to/renanfranca</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%2F792637%2F733e6698-784d-4f76-8e2f-888db5b58b20.jpeg</url>
      <title>DEV Community: Renan Franca</title>
      <link>https://dev.to/renanfranca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/renanfranca"/>
    <language>en</language>
    <item>
      <title>🔄 Just published a new article on enhancing CLI experiences! 🚀 I recently worked on an interesting UX challenge in the JHipster Lite CLI: users were left staring at blank screens during operations, unsure if things were working or frozen. 🤔</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Wed, 23 Jul 2025 16:08:28 +0000</pubDate>
      <link>https://dev.to/renanfranca/just-published-a-new-article-on-enhancing-cli-experiences-i-recently-worked-on-an-4mll</link>
      <guid>https://dev.to/renanfranca/just-published-a-new-article-on-enhancing-cli-experiences-i-recently-worked-on-an-4mll</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/renanfranca/adding-a-loading-animation-to-jhipster-lite-cli-25np" class="crayons-story__hidden-navigation-link"&gt;Adding a Loading Animation to JHipster Lite CLI&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/renanfranca" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F792637%2F733e6698-784d-4f76-8e2f-888db5b58b20.jpeg" alt="renanfranca profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/renanfranca" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Renan Franca
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Renan Franca
                
              
              &lt;div id="story-author-preview-content-2714549" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/renanfranca" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F792637%2F733e6698-784d-4f76-8e2f-888db5b58b20.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Renan Franca&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/renanfranca/adding-a-loading-animation-to-jhipster-lite-cli-25np" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 22 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/renanfranca/adding-a-loading-animation-to-jhipster-lite-cli-25np" id="article-link-2714549"&gt;
          Adding a Loading Animation to JHipster Lite CLI
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/java"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;java&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/renanfranca/adding-a-loading-animation-to-jhipster-lite-cli-25np" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/renanfranca/adding-a-loading-animation-to-jhipster-lite-cli-25np#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>java</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Adding a Loading Animation to JHipster Lite CLI</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Tue, 22 Jul 2025 16:20:08 +0000</pubDate>
      <link>https://dev.to/renanfranca/adding-a-loading-animation-to-jhipster-lite-cli-25np</link>
      <guid>https://dev.to/renanfranca/adding-a-loading-animation-to-jhipster-lite-cli-25np</guid>
      <description>&lt;p&gt;Have you ever run a command-line application and found yourself staring at a blank screen, wondering if it's still working or if it's frozen? That's exactly the problem I set out to solve for the JHipster Lite CLI project. In this post, I'll share how I implemented a loading animation to enhance the user experience while commands are executing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Waiting in the Dark
&lt;/h2&gt;

&lt;p&gt;When running commands in the JHipster Lite CLI, users had no visual feedback during operations that took more than a few seconds. This led to uncertainty - is the application still running? Is it stuck? Should I cancel and try again?&lt;/p&gt;

&lt;p&gt;I wanted to fix &lt;a href="https://github.com/jhipster/jhipster-lite-cli/issues/13" rel="noopener noreferrer"&gt;this issue&lt;/a&gt; by adding a loading animation that would provide visual feedback during command execution.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Solution: A Hexagonal ProgressStatus
&lt;/h2&gt;

&lt;p&gt;I created a loading animation module that follows the hexagonal architecture principles that JHipster Lite is known for. Here's a demo of what I implemented:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Exploring Available Libraries
&lt;/h2&gt;

&lt;p&gt;Before implementing my own solution, I explored existing libraries:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/lukfor/magic-progress" rel="noopener noreferrer"&gt;magic-progress&lt;/a&gt;&lt;/strong&gt;: I tried using this library but encountered errors when running the &lt;code&gt;jhlite&lt;/code&gt; command. Looking at the source code, I found no tests, and the project hadn't been maintained since August 2020.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/ctongfei/progressbar" rel="noopener noreferrer"&gt;progressbar&lt;/a&gt;&lt;/strong&gt;: This library didn't have spinner animations, which was a key requirement for our user experience.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Given these limitations, I decided to implement a custom solution that would perfectly fit our needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ProgressStatus Module
&lt;/h2&gt;

&lt;p&gt;I created a &lt;code&gt;ProgressStatus&lt;/code&gt; module following hexagonal architecture principles:&lt;/p&gt;

&lt;h3&gt;
  
  
  Hexagonal Architecture Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;├── domain
│   └── ProgressStatus.java
├── infrastructure
│   └── primary
│       └── SpinnerProgressStatus.java
└── package-info.java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code follows a clean hexagonal architecture pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Domain Layer (Port)&lt;/strong&gt; - The &lt;code&gt;ProgressStatus&lt;/code&gt; interface defines the core contract&lt;br&gt;
&lt;a href="https://gist.github.com/renanfranca/810ef56bfc0b62a2b02c7b3c4e4bb8fa" rel="noopener noreferrer"&gt;ProgressStatus.java - (click to expand)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infrastructure Layer (Adapter)&lt;/strong&gt; - The &lt;code&gt;SpinnerProgressStatus&lt;/code&gt; class implements the interface for spinner animation&lt;br&gt;
&lt;a href="https://gist.github.com/renanfranca/f673c7098e71392d1e623d3efcaf273e" rel="noopener noreferrer"&gt;SpinnerProgressStatus.java - (click to expand)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This separation allows us to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep the core logic independent of visual animation implementation&lt;/li&gt;
&lt;li&gt;Easily test with mock implementations&lt;/li&gt;
&lt;li&gt;Add new progress indicator types without changing core logic&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h4&gt;
  
  
  1. Animated Unicode Spinner
&lt;/h4&gt;

&lt;p&gt;The spinner uses Unicode braille patterns for a smooth rotating animation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="no"&gt;SPINNER_FRAMES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"⠋"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠙"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠹"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠸"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠼"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠴"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠦"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠧"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠇"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"⠏"&lt;/span&gt; &lt;span class="o"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Color-Coded Messages
&lt;/h4&gt;

&lt;p&gt;The animation implements ANSI color support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cyan for in-progress operations&lt;/li&gt;
&lt;li&gt;Green for success messages&lt;/li&gt;
&lt;li&gt;Red for failure notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Asynchronous Animation
&lt;/h4&gt;

&lt;p&gt;The spinner runs in a daemon thread to avoid blocking the main application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newSingleThreadScheduledExecutor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;Thread&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"spinner-animation"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setDaemon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;scheduleAtFixedRate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;renderFrame&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MILLISECONDS&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Thread-Safe Operation
&lt;/h4&gt;

&lt;p&gt;The implementation uses atomic operations for thread safety:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;AtomicBoolean&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AtomicBoolean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Rich Animation Sequences
&lt;/h4&gt;

&lt;p&gt;I added sophisticated animation cycles including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Progressive dots (. .. ...)&lt;/li&gt;
&lt;li&gt;JHipster-lite symbols (⧓⚡)&lt;/li&gt;
&lt;li&gt;Hexagonal architecture symbol (💎)&lt;/li&gt;
&lt;li&gt;Spring Boot symbol (🍃)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  6. Rendering Animation Logic
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;renderSpinner&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;updateFrame&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;running&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;updateFrame&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="n"&gt;frameIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frameIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="no"&gt;SPINNER_FRAMES&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
     &lt;span class="n"&gt;suffixFrameIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;suffixFrameIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="no"&gt;SUFFIX_ANIMATION_FRAMES&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
   &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SPINNER_FRAMES&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;frameIndex&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
   &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;suffix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SUFFIX_ANIMATION_FRAMES&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;suffixFrameIndex&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
   &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CLEAR_LINE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;ANSI_CYAN&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;ANSI_RESET&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;currentMessage&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Little Details That Matter
&lt;/h2&gt;

&lt;p&gt;A cool thing about this animation is that you don't mind if operations take a little longer because you can see different animations and progress indicators. I included some curious details:&lt;/p&gt;

&lt;p&gt;1) The icons on the right represent the technology and architecture used by JHLiteCli. I synchronized the animation so it feels like you can see what is loading, but it's just an illusion.&lt;/p&gt;

&lt;p&gt;2) If the Execute command takes a little bit longer, it shows the bow tie + lightning, which represents jhipster-lite. I designed the animation to match that style.&lt;/p&gt;

&lt;p&gt;At the end, I felt the loading time isn't as bothersome as before. The user experience is much more relaxed and engaging.&lt;/p&gt;

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

&lt;p&gt;Here's a test case on how ProgressStatus works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Test&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldShowSuccessMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CapturedOutput&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="nc"&gt;ProgressStatus&lt;/span&gt; &lt;span class="n"&gt;progressStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SpinnerProgressStatus&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
   &lt;span class="n"&gt;progressStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;show&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Operation in progress"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;progressStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Completed successfully"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;assertThat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"✓"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Completed successfully"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://gist.github.com/renanfranca/e8b1618ef65557239a486f358ab6f5fe" rel="noopener noreferrer"&gt;ProgressStatusTest.java - (click to expand)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits Beyond Aesthetics
&lt;/h2&gt;

&lt;p&gt;This implementation provides several benefits:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Improved User Experience&lt;/strong&gt;: Users now have visual feedback during operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Perceived Wait Time&lt;/strong&gt;: The animation makes waiting feel shorter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clear Operation Status&lt;/strong&gt;: Success and failure states are clearly indicated&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architectural Consistency&lt;/strong&gt;: The solution follows JHipster's hexagonal architecture principles&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;I am going to share how I integrated the ProgressStatus module into the JHipster Lite CLI for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Application Startup&lt;/strong&gt;: Shows "Loading JHipster Lite CLI" during initialization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command Execution&lt;/strong&gt;: Displays progress during command running&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command Completion&lt;/strong&gt;: Shows success or failure messages with appropriate colors&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The animation is going to be active for all major commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version command (--version)&lt;/li&gt;
&lt;li&gt;List command (list)&lt;/li&gt;
&lt;li&gt;Apply command (apply)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Adding a loading animation to the JHipster Lite CLI might seem like a small enhancement, but it significantly improves the user experience. By following hexagonal architecture principles, I was able to create a solution that's not only visually appealing but also maintainable, testable, and extensible.&lt;/p&gt;

&lt;p&gt;This project demonstrates how proper architectural design can benefit even UI components. The next time you're working on a command-line application, consider how you might enhance the user experience with similar feedback mechanisms.&lt;/p&gt;

&lt;p&gt;Lastly, let me extend an invitation to join me on my journey 🚀 in the realm of software development. I share my insights, experiences, and valuable resources on &lt;a href="https://www.linkedin.com/in/renan-af" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; 📎. Following me on these platforms not only keeps you updated on my latest posts and projects 📬 but also opens doors to vibrant discussions and learning opportunities. I look forward to connecting with you! 💼&lt;/p&gt;

</description>
      <category>java</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>[Boost] My Journey to the JHipster Core Team</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Thu, 10 Jul 2025 15:44:46 +0000</pubDate>
      <link>https://dev.to/renanfranca/-62l</link>
      <guid>https://dev.to/renanfranca/-62l</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/renanfranca/my-journey-to-the-jhipster-core-team-5198" class="crayons-story__hidden-navigation-link"&gt;My Journey to the JHipster Core Team&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/renanfranca" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F792637%2F733e6698-784d-4f76-8e2f-888db5b58b20.jpeg" alt="renanfranca profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/renanfranca" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Renan Franca
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Renan Franca
                
              
              &lt;div id="story-author-preview-content-2675400" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/renanfranca" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F792637%2F733e6698-784d-4f76-8e2f-888db5b58b20.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Renan Franca&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/renanfranca/my-journey-to-the-jhipster-core-team-5198" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 10 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/renanfranca/my-journey-to-the-jhipster-core-team-5198" id="article-link-2675400"&gt;
          My Journey to the JHipster Core Team
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/jhipster"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;jhipster&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/beginners"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;beginners&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/renanfranca/my-journey-to-the-jhipster-core-team-5198" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/renanfranca/my-journey-to-the-jhipster-core-team-5198#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>jhipster</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>My Journey to the JHipster Core Team</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Thu, 10 Jul 2025 15:40:18 +0000</pubDate>
      <link>https://dev.to/renanfranca/my-journey-to-the-jhipster-core-team-5198</link>
      <guid>https://dev.to/renanfranca/my-journey-to-the-jhipster-core-team-5198</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/my-journey-to-the-jhipster-core-team.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's been 18 months since I joined the &lt;a href="https://www.jhipster.tech/team/" rel="noopener noreferrer"&gt;JHipster core team&lt;/a&gt;, and what an incredible journey it has been! Today I want to reflect on how it all started back in January 2024 when I was elected to join the team after a successful vote by the members. 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  My Path to the Core Team
&lt;/h2&gt;

&lt;p&gt;My relationship with JHipster has been transformative:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;🚀 It quickly turned into my main side project, where I get to apply the techniques I'm learning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🛠️ Here, I truly discovered the power of Test-Driven Development (TDD).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;📚 Always growing and learning with this amazing community! 😊&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🎉 The pinnacle came when I was elected to join the JHipster core team in January 2024.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Introduced Myself
&lt;/h2&gt;

&lt;p&gt;When I joined the core team in January 2024, here's how I introduced myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My name is Renan Franca, and I have been a software engineer since 2008. I am a big fan of JHipster! I first encountered JHipster in 2021 while creating a side project to monitor my baby girl's status: &lt;a href="https://renanfranca.github.io/i-built-a-baby-care-web-app-using-jhipster.html" rel="noopener noreferrer"&gt;https://renanfranca.github.io/i-built-a-baby-care-web-app-using-jhipster.html&lt;/a&gt; Since then, I have been maintaining a blog to promote JHipster &lt;a href="https://renanfranca.github.io" rel="noopener noreferrer"&gt;https://renanfranca.github.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My first contribution to the jhipster-generator was on 07/2021: &lt;a href="https://github.com/jhipster/generator-jhipster/pull/15724" rel="noopener noreferrer"&gt;https://github.com/jhipster/generator-jhipster/pull/15724&lt;/a&gt;. After blogging for a while, I decided to contribute to the JHipster Lite project and wrote about the experience here: &lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html" rel="noopener noreferrer"&gt;https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html&lt;/a&gt;. Then, I made 10 contributions to the JHipster Lite project (&lt;a href="https://github.com/jhipster/jhipster-lite/pulls?q=is%3Apr+author%3A%40me+is%3Aclosed" rel="noopener noreferrer"&gt;https://github.com/jhipster/jhipster-lite/pulls?q=is%3Apr+author%3A%40me+is%3Aclosed&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I'd like to join the core team because I truly love this project and the community. Recently, I realized my ambition isn't to create new side projects anymore. Now, my goal is to adopt the JHipster project as my primary side project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  My Contribution Journey
&lt;/h2&gt;

&lt;p&gt;My contributions until today (2025-07-10):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I contributed with more than &lt;a href="https://github.com/jhipster/jhipster-lite/pulls?q=is%3Apr+author%3Arenanfranca+is%3Amerged+" rel="noopener noreferrer"&gt;73 merged Pull Requests&lt;/a&gt; at &lt;a href="https://github.com/jhipster/jhipster-lite" rel="noopener noreferrer"&gt;JHipster Lite Project&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I also contributed to the &lt;a href="https://github.com/jhipster/jhipster-lite-extension" rel="noopener noreferrer"&gt;JHipster Lite Extension project&lt;/a&gt; with &lt;a href="https://github.com/jhipster/jhipster-lite-extension/pulls?q=is%3Apr+author%3Arenanfranca+is%3Amerged+" rel="noopener noreferrer"&gt;7 merged Pull Requests&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I am currently working on the CLI version of JHLite called &lt;a href="https://github.com/jhipster/jhipster-lite-cli" rel="noopener noreferrer"&gt;JHipster Lite CLI Project&lt;/a&gt;, with &lt;a href="https://github.com/jhipster/jhipster-lite-cli/pulls?q=is%3Apr+author%3Arenanfranca+is%3Amerged+" rel="noopener noreferrer"&gt;9 Pull Requests merged&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This CLI project was the first major project I built using jhipster-lite to assist me, marking my first coding experience with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Wishful Thinking to Reality
&lt;/h2&gt;

&lt;p&gt;Back in January 2023, I wrote a post about &lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html" rel="noopener noreferrer"&gt;how I earned money by fixing an issue in JHipster Lite&lt;/a&gt;. At the end of that post, I shared a goal that was close to my heart:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I am planning to continue to contribute to the jhlite project by fixing issues and keep writing blog posts about my experience with jhipster.&lt;/p&gt;

&lt;p&gt;One day, I wish to be part of the &lt;a href="https://www.jhipster.tech/team/" rel="noopener noreferrer"&gt;jhipster core team&lt;/a&gt; 😊!"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's incredible how aspirations can become reality when you're persistent and passionate about what you do. Just one year after writing those words, what seemed like a distant dream became true when I was elected to join the core team! &lt;/p&gt;

&lt;p&gt;This journey shows the power of setting goals and consistently working toward them. Through each pull request, each blog post, and each interaction with the community, I was building the path that would eventually lead me to where I am today.&lt;/p&gt;

&lt;h2&gt;
  
  
  18 Months of Growth
&lt;/h2&gt;

&lt;p&gt;The past year and a half as a core team member has been filled with learning, collaboration, and growth. I've had the opportunity to work alongside incredibly talented developers, contribute to major releases, and help shape the future of JHipster.&lt;/p&gt;

&lt;p&gt;Being part of this community has reinforced my belief in the power of open source and collaborative development. The skills I've gained and the connections I've made have been invaluable not just to my work with JHipster, but to my career as a whole.&lt;/p&gt;

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

&lt;p&gt;As I look ahead to the future, I'm excited about the continued evolution of JHipster and my role within it. There are always new challenges to tackle, features to implement, and improvements to make.&lt;/p&gt;

&lt;p&gt;I'm grateful for the trust placed in me by the JHipster community, and I remain committed to contributing my best work to this project that has become such an important part of my professional journey.&lt;/p&gt;

&lt;p&gt;Lastly, let me extend an invitation to join me on my journey 🚀 in the realm of software development. I share my insights, experiences, and valuable resources on &lt;a href="https://www.linkedin.com/in/renan-af" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; 📎. Following me on these platforms not only keeps you updated on my latest posts and projects 📬 but also opens doors to vibrant discussions and learning opportunities. I look forward to connecting with you! 💼&lt;/p&gt;

</description>
      <category>jhipster</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>💨🚀 Accelerate Your Workflow with ChatGPT Prompts 📝 - Ditch the Boilerplate 📃✖️ and Eliminate Duplicates 🔄🚫</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Wed, 12 Jul 2023 10:49:41 +0000</pubDate>
      <link>https://dev.to/renanfranca/accelerate-your-workflow-with-chatgpt-prompts-ditch-the-boilerplate-and-eliminate-duplicates-p14</link>
      <guid>https://dev.to/renanfranca/accelerate-your-workflow-with-chatgpt-prompts-ditch-the-boilerplate-and-eliminate-duplicates-p14</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/accelerate-workflow-chatgpt-prompt.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In our ever-evolving digital landscape, efficiency is the name of the game. As developers, we're constantly on the hunt for tools and practices that can streamline our workflow and improve the quality of our code. One powerful approach to achieving this is through the use of AI-based prompts, specifically, OpenAI's ChatGPT prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unraveling Boilerplate Code
&lt;/h2&gt;

&lt;p&gt;Boilerplate code refers to sections of code that have to be included in many places with little to no alteration. It's often necessary but can bloat our codebase, making it harder to read and maintain. Moreover, the act of constantly typing out these code sections is time-consuming and monotonous.&lt;/p&gt;

&lt;p&gt;This is where the beauty of ChatGPT prompts comes into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  Harnessing the Power of ChatGPT Prompts
&lt;/h2&gt;

&lt;p&gt;ChatGPT prompts can drastically speed up the development process by automating the generation of boilerplate code. This not only reduces manual typing but also minimizes the risk of errors that often creep in during repetitive tasks like copying and pasting code. I will show you some examples using chatGPT-4.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Practical Example: From JSON to Typescript object
&lt;/h3&gt;

&lt;p&gt;As the first example, I will introduce a simple prompt for you to get used to it before going to complex prompts.&lt;/p&gt;

&lt;p&gt;Imagine you have a JSON that needs to be converted to a Typescript object. Here's a sample prompt you could use:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; Convert the following JSON to a Typescript object:&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"details"&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;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123 Main St"&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;With the help of ChatGPT, the output would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Details&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Details&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;john@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;details&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123 Main St&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a simple prompt, we managed to convert a JSON object to a Typescript object, significantly reducing the time and effort required for this common task.&lt;/p&gt;

&lt;p&gt;Try out this prompt right now: &lt;a href="https://chat.openai.com/share/5e162d6c-489f-4a31-a710-41b484b0d2d5"&gt;TS Object from JSON&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ditching Boilerplate with Prompts
&lt;/h3&gt;

&lt;p&gt;I like to organize my Vuejs components in different files, for example, a component called Homepage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📂homepage

&lt;ul&gt;
&lt;li&gt;Homepage.component.ts&lt;/li&gt;
&lt;li&gt;Homepage.html&lt;/li&gt;
&lt;li&gt;HomepageVue.vue&lt;/li&gt;
&lt;li&gt;index.ts&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;The following prompt generates the content of those files for a different component name:&lt;/p&gt;

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

&lt;p&gt;In vue 3 js, take into account the organization of this file inside the folder homepage:&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="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;HomepageVue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./HomepageVue.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HomepageVue&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;HomepageVue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Homepage.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Homepage.component.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Homepage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Homepage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&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;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HomepageVue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you are going to ask me for the name of the new component and replace Homepage with the new component name. After that, you are going to ask for other component names again forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;: Sure, I can assist you with that. To start, what is the name of your new component?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt&lt;/strong&gt;: SignIn&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Based on your request, your files for the new component "SignIn" should be structured as follows:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;index.ts:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;SignInVue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./SignInVue.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SignInVue&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;SignInVue.vue:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./SignIn.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./SignIn.component.ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;SignIn.html:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;SignIn.component.ts:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SignInVue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Let's continue. What is the next component name you would like to use?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then I could keep creating new components and copy and paste them into my Vuejs project 😎!&lt;/p&gt;

&lt;p&gt;Check this prompt right now: &lt;a href="https://chat.openai.com/share/87618651-9bd0-40df-84b1-f2cab05ac399"&gt;Generate Vuejs Component&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ditching Duplicates with Prompts
&lt;/h3&gt;

&lt;p&gt;ChatGPT is not just limited to boilerplate code; it can also be employed to identify and refactor duplicated code, another common concern in software development.&lt;/p&gt;

&lt;p&gt;Let's say we have a software system for a library. The system has two main functionalities: lending books to library members and restocking returned books.&lt;/p&gt;

&lt;p&gt;Below is the code which has a significant amount of duplication and the prompt you could use at the:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt&lt;/strong&gt;:&lt;br&gt;
Remove the duplication from the following Java class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LibrarySystem&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Member&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// other necessary code...&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;lendBook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Member&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// removing the book from the available book list&lt;/span&gt;
            &lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// adding the book to the member's lent books&lt;/span&gt;
            &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;memberBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memberBooks&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;memberBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
                &lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memberBooks&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;memberBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// generating a due date for returning the book, let's say in two weeks&lt;/span&gt;
            &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;dueDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;plusWeeks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// printing out a receipt&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Book: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" lent to: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" Due date: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dueDate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// other necessary code...&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The book is not available."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;restockBook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Member&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// removing the book from the member's lent books&lt;/span&gt;
            &lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// adding the book to the available book list&lt;/span&gt;
            &lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// calculating and printing out any late fees&lt;/span&gt;
            &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;dueDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;minusWeeks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// assuming the book was due two weeks ago&lt;/span&gt;
            &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;returnDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;returnDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAfter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dueDate&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;daysLate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChronoUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DAYS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;between&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dueDate&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;returnDate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;lateFee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;daysLate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.50&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// assuming the late fee is 50 cents per day&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Late fee for book: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" is: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;lateFee&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// other necessary code...&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The book was not lent to this member."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The duplication in this Java class can be seen in the code that retrieves a member's book list from the map. This code segment is repeated in both methods, &lt;code&gt;lendBook&lt;/code&gt;, and &lt;code&gt;restockBook&lt;/code&gt;. To remove this duplication, you can create a helper method, &lt;code&gt;getMemberBooks&lt;/code&gt;, which takes a &lt;code&gt;Member&lt;/code&gt; as an argument and returns a &lt;code&gt;List&amp;lt;Book&amp;gt;&lt;/code&gt;. Here is the refactored code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LibrarySystem&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Member&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// other necessary code...&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getMemberBooks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Member&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;memberBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memberBooks&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;memberBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;lentBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;memberBooks&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;memberBooks&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;lendBook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Member&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// removing the book from the available book list&lt;/span&gt;
            &lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// adding the book to the member's lent books&lt;/span&gt;
            &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;memberBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getMemberBooks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;memberBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// generating a due date for returning the book, let's say in two weeks&lt;/span&gt;
            &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;dueDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;plusWeeks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// printing out a receipt&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Book: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" lent to: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" Due date: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dueDate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// other necessary code...&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The book is not available."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;restockBook&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Member&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Book&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Book&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;memberBooks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getMemberBooks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memberBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// removing the book from the member's lent books&lt;/span&gt;
            &lt;span class="n"&gt;memberBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// adding the book to the available book list&lt;/span&gt;
            &lt;span class="n"&gt;availableBooks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="c1"&gt;// calculating and printing out any late fees&lt;/span&gt;
            &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;dueDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;minusWeeks&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// assuming the book was due two weeks ago&lt;/span&gt;
            &lt;span class="nc"&gt;LocalDate&lt;/span&gt; &lt;span class="n"&gt;returnDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LocalDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;returnDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAfter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dueDate&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;daysLate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChronoUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DAYS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;between&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dueDate&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;returnDate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
                &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;lateFee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;daysLate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.50&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// assuming the late fee is 50 cents per day&lt;/span&gt;
                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Late fee for book: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTitle&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" is: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;lateFee&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// other necessary code...&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The book was not lent to this member."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By simply running a ChatGPT prompt to identify and refactor duplicated code, we streamlined our code, enhancing readability and maintainability.&lt;/p&gt;

&lt;p&gt;This prompt is available here: &lt;a href="https://chat.openai.com/share/7986d984-0220-45fb-9ccf-501cb810ecd9"&gt;Remove Duplication in Java&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Connect and Continue the Discussion 🚀
&lt;/h2&gt;

&lt;p&gt;My journey as a developer is marked by the constant pursuit of knowledge and efficiency. I've found the usage of ChatGPT prompts to be a powerful tool for achieving these goals, and I'm excited to share these insights with the community.&lt;/p&gt;

&lt;p&gt;To continue this journey together, I extend an invitation to connect with me on Twitter &lt;a href="https://www.twitter.com/renan_afranca"&gt;@renan_afranca&lt;/a&gt;🐦 and &lt;a href="https://www.linkedin.com/in/renan-af"&gt;LinkedIn&lt;/a&gt;📎. Not only will you stay updated with my latest posts and insights, but it will also pave the way for fruitful discussions and learning opportunities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Turn 💼
&lt;/h2&gt;

&lt;p&gt;How has your experience been with AI-assisted code generation? Do you see the use of prompts like ChatGPT becoming a staple in software development workflows? How have these prompts impacted your productivity or code quality?&lt;/p&gt;

&lt;p&gt;Drop your thoughts 💭 in the comment section below and let's foster a healthy discussion around enhancing developer experiences in our digital era. Looking forward to your valuable input! 🌟&lt;/p&gt;

&lt;h2&gt;
  
  
  📣 Attention all tech enthusiasts, coders, and lifelong learners!
&lt;/h2&gt;

&lt;p&gt;I have some intriguing blog posts that you just can't afford to miss!&lt;/p&gt;

&lt;p&gt;🚀 Discover the art of perfecting your Github profile with the guide &lt;a href="https://renanfranca.github.io/2022/03/17/create-a-github-stunning-profile.html"&gt;&lt;strong&gt;"Create a Github Stunning Profile"&lt;/strong&gt;&lt;/a&gt;. This article won't just teach you how to make your profile aesthetically pleasing, but also help you dynamically list your recent blog posts. Say goodbye to manual updates and hello to automation. Make your Github profile a mirror of your tech prowess! 💫&lt;/p&gt;

&lt;p&gt;🧩 Ever wondered why JHipster avoids Lombok? Delve deep into the pros and cons of using Lombok and why JHipster chooses to walk a different path in my thought-provoking post &lt;a href="https://renanfranca.github.io/jhipster-does-not-use-lombok-why.html"&gt;"&lt;strong&gt;JHipster Does Not Use Lombok. Why?&lt;/strong&gt;"&lt;/a&gt; Unravel this technological mystery and gain insights into industry practices that you can implement in your own projects.&lt;/p&gt;

&lt;p&gt;📱 Want to code on the go? Check out my definitive guide &lt;a href="https://renanfranca.github.io/2022/03/02/vscode-on-android.html"&gt;"&lt;strong&gt;VSCode on Android (you don’t need to install anything)&lt;/strong&gt;"&lt;/a&gt;. This gem of a blog post will break down how to use Visual Studio Code on Android without the hassle of installation. Transform your Android device into a coding machine and get things done wherever you are.&lt;/p&gt;

&lt;p&gt;No matter where you are in your tech journey, these posts will enlighten you, challenge you, and push you forward. Don't let this opportunity pass you by, read these posts now! Ignite your passion for technology and continue to expand your knowledge with us. 💡&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Your Guide to Implementing Vue Placeholder Loading</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Mon, 26 Jun 2023 10:41:10 +0000</pubDate>
      <link>https://dev.to/renanfranca/your-guide-to-implementing-vue-placeholder-loading-11df</link>
      <guid>https://dev.to/renanfranca/your-guide-to-implementing-vue-placeholder-loading-11df</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/implementing-placeholder-loading-in-vue.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In today's fast-paced digital world, user experience is paramount. As developers, we're always looking for ways to make our applications more responsive and enjoyable. One effective strategy to enhance the user experience is by using placeholder loading, or skeleton loading, in our Vue.js applications.&lt;/p&gt;

&lt;p&gt;Placeholder loading is a technique where a simplified version of the web page is shown while the full content is being loaded. This approach gives users immediate feedback that content is on the way, resulting in a smoother, more engaging experience. But how do we effectively implement placeholder loading in Vue.js applications?&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter placeholder-loading
&lt;/h2&gt;

&lt;p&gt;An easy and efficient way to implement placeholder loading is through the &lt;a href="https://www.npmjs.com/package/placeholder-loading" rel="noopener noreferrer"&gt;&lt;code&gt;placeholder-loading&lt;/code&gt;&lt;/a&gt; npm package. This simple and flexible library uses CSS-only content placeholders, providing a sleek loading animation.&lt;/p&gt;

&lt;p&gt;To use &lt;code&gt;placeholder-loading&lt;/code&gt; in your Vue.js project, you can install it via npm and import it into your application:&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;placeholder-loading &lt;span class="nt"&gt;--save&lt;/span&gt;
@import &lt;span class="s2"&gt;"~/node_modules/placeholder-loading/src/scss/placeholder-loading"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This library allows you to modify various SASS variables to suit your project's aesthetics, such as direction, background color, border properties, grid configuration, and animation duration.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;placeholder-loading&lt;/code&gt; is as simple as including specific classes in your HTML markup. Here's an example of how you can use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-picture"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-6 big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-4 empty big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-2 big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-8 empty"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-6"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-6 empty"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, &lt;code&gt;.ph-item&lt;/code&gt;, &lt;code&gt;.ph-col-*&lt;/code&gt;, &lt;code&gt;.ph-picture&lt;/code&gt;, and &lt;code&gt;.ph-row&lt;/code&gt; are all classes provided by &lt;code&gt;placeholder-loading&lt;/code&gt;. See some live examples here: &lt;a href="https://zalog.ro/placeholder-loading/" rel="noopener noreferrer"&gt;https://zalog.ro/placeholder-loading/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Practical Example
&lt;/h2&gt;

&lt;p&gt;To better illustrate the use of placeholder loading in Vue.js, let's examine a real-world example from a pull request I recently made to the &lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html#learn-about-the-jhipster-lite-project" rel="noopener noreferrer"&gt;jhipster-lite&lt;/a&gt; repository on GitHub: &lt;a href="https://github.com/jhipster/jhipster-lite/pull/6247" rel="noopener noreferrer"&gt;add placeholder during load #6247&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this pull request, I added placeholder loading to the &lt;code&gt;LandscapeLoader&lt;/code&gt; and &lt;code&gt;ModulesPatchLoader&lt;/code&gt; components. Those components are responsible for displaying a placeholder while the actual content is loading. To achieve this, I used the &lt;code&gt;placeholder-loading&lt;/code&gt; library along with Vue.js components for rows, pictures, and lists.&lt;/p&gt;

&lt;p&gt;Let's take a look at the Landscape screen using the &lt;code&gt;LandscapeLoader&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fimplementing-placeholder-loading%2Flandscape-loader.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fimplementing-placeholder-loading%2Flandscape-loader.jpg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Landscape Skeleton Loading Screen



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fimplementing-placeholder-loading%2Flandscape-screen.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fimplementing-placeholder-loading%2Flandscape-screen.jpg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Landscape screen loaded



&lt;p&gt;Here is the ModulePatch screen using the &lt;code&gt;ModulesPatchLoader&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fimplementing-placeholder-loading%2Fmodulepatch-loader.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fimplementing-placeholder-loading%2Fmodulepatch-loader.jpg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
ModulePatch Skeleton Loading Screen



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fimplementing-placeholder-loading%2Fmodulepatch-screen.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fimplementing-placeholder-loading%2Fmodulepatch-screen.jpg" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
ModulePatch screen loaded



&lt;p&gt;I choose to detail the implementation of the &lt;code&gt;ModulesPatchLoader&lt;/code&gt; because it is easy to understand. Follow me through 8 steps to implementing it!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step I: package.json
&lt;/h3&gt;

&lt;p&gt;Here, I'd like to discuss a key change I made to the &lt;code&gt;package.json&lt;/code&gt; file in a Node.js project. This file is crucial as it contains project metadata and the dependencies required for the project to function correctly.&lt;/p&gt;

&lt;p&gt;Here is the modified code:&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;"dependencies"&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;"axios"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.4.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mitt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"placeholder-loading"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.6.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3.3.4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vue-router"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4.2.1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Line by line, let's break this down. The &lt;code&gt;axios&lt;/code&gt; and &lt;code&gt;mitt&lt;/code&gt; dependencies remained unchanged at versions "1.4.0" and "3.0.0" respectively. The &lt;code&gt;vue&lt;/code&gt; and &lt;code&gt;vue-router&lt;/code&gt; dependencies also remained consistent in versions "3.3.4" and "4.2.1".&lt;/p&gt;

&lt;p&gt;The key change was the addition of a new dependency - &lt;code&gt;placeholder-loading&lt;/code&gt;. This was introduced with a version specifier of "^0.6.0". This syntax is specific to npm, the Node.js package manager, and it indicates that npm will install the latest minor version that is greater than or equal to &lt;code&gt;0.6.0&lt;/code&gt;. For instance, if there are versions &lt;code&gt;0.6.1&lt;/code&gt;, &lt;code&gt;0.6.2&lt;/code&gt;, &lt;code&gt;0.7.0&lt;/code&gt; available, npm will install &lt;code&gt;0.7.0&lt;/code&gt;. However, if there's &lt;code&gt;0.8.0&lt;/code&gt;, it would not install this as &lt;code&gt;0.8.0&lt;/code&gt; would be considered a major version.&lt;/p&gt;

&lt;p&gt;Adding the &lt;code&gt;placeholder-loading&lt;/code&gt; package to the project's dependencies, allows the project to use the functionality provided by this package, which was critical to the enhancement I was working on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step II: vite.config.ts
&lt;/h3&gt;

&lt;p&gt;Let's break down the changes I made in the code, line by line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;preprocessorOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;scss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;additionalData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
          @import "@/assets/global.scss";
          @import "@/assets/side-form.scss";
          @import "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules/placeholder-loading/dist/css/placeholder-loading.min.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;";`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;css&lt;/code&gt; property, the &lt;code&gt;preprocessorOptions&lt;/code&gt; is set to use SCSS, a CSS preprocessor which makes writing CSS more powerful and maintainable. The &lt;code&gt;additionalData&lt;/code&gt; property allows us to add more SCSS resources.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@import&lt;/code&gt; statement is used to import the styles from other SCSS files. The first two imports, &lt;code&gt;"@/assets/global.scss"&lt;/code&gt; and &lt;code&gt;"@/assets/side-form.scss"&lt;/code&gt;, are from the original code and load global and side form styles respectively.&lt;/p&gt;

&lt;p&gt;The new line I introduced imports the &lt;code&gt;placeholder-loading.min.css&lt;/code&gt; from the placeholder-loading package, which is a framework for creating a placeholder loading effect. The path to the &lt;code&gt;placeholder-loading.min.css&lt;/code&gt; file is resolved using Node's &lt;code&gt;path.resolve&lt;/code&gt; method, which resolves a sequence of paths into an absolute path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step III: ModulesPatch.html
&lt;/h3&gt;

&lt;p&gt;In the initial state of the code, a &lt;code&gt;div&lt;/code&gt; element with classes "jhipster-modules" and "jhlite-loader-container" was used to display the loading state. This display was conditioned on the &lt;code&gt;isLoading&lt;/code&gt; method of the &lt;code&gt;content&lt;/code&gt; object. Inside this &lt;code&gt;div&lt;/code&gt;, there was another &lt;code&gt;div&lt;/code&gt; with the class "jhlite-loader" that presumably handled the actual display of the loading state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhipster-modules jhlite-loader-container"&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"content.isLoading()"&lt;/span&gt; &lt;span class="na"&gt;data-selector=&lt;/span&gt;&lt;span class="s"&gt;"modules-loader"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhlite-loader"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhipster-modules jhlite-menu-content-template"&lt;/span&gt; &lt;span class="na"&gt;v-else&lt;/span&gt; &lt;span class="na"&gt;data-selector=&lt;/span&gt;&lt;span class="s"&gt;"modules-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhipster-modules-list jhlite-menu-content-template--content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhipster-modules-filters"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the improved version of the code, the &lt;code&gt;div&lt;/code&gt; has been replaced with a Vue component called &lt;code&gt;ModulesPatchLoaderVue&lt;/code&gt;. This component is also dependent on the &lt;code&gt;isLoading&lt;/code&gt; method of the &lt;code&gt;content&lt;/code&gt; object to determine when to display. This change encapsulates the loading display logic within a reusable Vue component, making the code cleaner and more maintainable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ModulesPatchLoaderVue&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"content.isLoading()"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhipster-modules jhlite-menu-content-template"&lt;/span&gt; &lt;span class="na"&gt;v-else&lt;/span&gt; &lt;span class="na"&gt;data-selector=&lt;/span&gt;&lt;span class="s"&gt;"modules-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhipster-modules-list jhlite-menu-content-template--content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhipster-modules-filters"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step IV: ModulesPatch.component.ts
&lt;/h3&gt;

&lt;p&gt;Here's the modified code snippet:&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;ModuleParametersVue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../module-parameters&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;castValue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../PropertyValue&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;ModuleParametersRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/module/domain/ModuleParametersRepository&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;ModulesPatchLoaderVue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../modules-patch-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ModulesPatchVue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ModuleParametersVue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IconVue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TagFilterVue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModulePropertiesFormVue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ProjectActionsVue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModulesPatchLoaderVue&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;alertBus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alertBus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AlertBus&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;modules&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ModulesRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Starting from the top, the imports section of the code remained largely the same, but with the addition of one crucial line: &lt;code&gt;import { ModulesPatchLoaderVue } from '../modules-patch-loader';&lt;/code&gt;. This line imports the &lt;code&gt;ModulesPatchLoaderVue&lt;/code&gt; component, which was added as part of the solution to improve the page loading experience.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;defineComponent&lt;/code&gt; function, the new &lt;code&gt;ModulesPatchLoaderVue&lt;/code&gt; component was added to the &lt;code&gt;components&lt;/code&gt; object. This means that the &lt;code&gt;ModulesPatchLoaderVue&lt;/code&gt; component is now accessible within the &lt;code&gt;ModulesPatchVue&lt;/code&gt; component, and can be used to display a more aesthetically pleasing loading placeholder when the page is loading.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;setup&lt;/code&gt; function remained untouched, but it's worth noting that it injects instances of &lt;code&gt;alertBus&lt;/code&gt; and &lt;code&gt;modules&lt;/code&gt; for use within the component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step V: modules-patch-loader/index.ts
&lt;/h3&gt;

&lt;p&gt;The changes are straightforward - it imports the Vue component &lt;code&gt;ModulesPatchLoaderVue&lt;/code&gt; from &lt;code&gt;ModulesPatchLoader.vue&lt;/code&gt; and then exports it. Here's the code:&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="nx"&gt;ModulesPatchLoaderVue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./ModulesPatchLoader.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ModulesPatchLoaderVue&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kind of file is standard in JavaScript and TypeScript projects. It brings a significant improvement to the way we handle imports in our code. The magic lies in its ability to allow importing directly from the &lt;code&gt;modules-patch-loader&lt;/code&gt; directory, without the need to specify the &lt;code&gt;.vue&lt;/code&gt; file. This results in cleaner and more readable code. Here's how you can now import the &lt;code&gt;ModulesPatchLoaderVue&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ModulesPatchLoaderVue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../modules-patch-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This replaces the more verbose, previous method:&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="nx"&gt;ModulesPatchLoaderVue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../modules-patch-loader/ModulesPatchLoader.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By streamlining the way we import the &lt;code&gt;ModulesPatchLoaderVue&lt;/code&gt;, we make our code more maintainable and intuitive to navigate, thereby enhancing our overall code quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step VI:  modules-patch-loader/ModulesPatchLoader.vue
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ModulesPatchLoader.vue&lt;/code&gt; file is a Vue Single File Component (SFC), essentially an all-in-one file containing a &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt;, a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, and a &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag, each referring to an external HTML, TypeScript, and SCSS file respectively.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; tag in this component points to the external &lt;code&gt;ModulesPatchLoader.html&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./ModulesPatchLoader.html"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag links to the &lt;code&gt;ModulesPatchLoader.component.ts&lt;/code&gt; TypeScript file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./ModulesPatchLoader.component.ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; tag introduces SCSS styles that define the appearance of the component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt; &lt;span class="nt"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"scss"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.jhlite-modules-loader-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;jhipster-lite-secondary-color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;jhipster-lite-primary-text-color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;.ph-item&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;jhipster-lite-secondary-color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.ph-jhlite-modules-container-content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-grow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-basis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;.modules-filter&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.modules-list&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-grow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow-y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.ph-jhlite-modules-sidemenu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="err"&gt;&amp;amp;-top&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-grow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;flex-basis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;-bottom&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;110px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;flex-grow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;flex-basis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.jhlite-modules-loader-content&lt;/code&gt; class sets a background color and a text color, while also adjusting the border and background color of items with the &lt;code&gt;.ph-item&lt;/code&gt; class. The &lt;code&gt;.ph-jhlite-modules-container-content&lt;/code&gt; class dictates the flexbox properties for layout control, and adjusts the height of the &lt;code&gt;.modules-filter&lt;/code&gt; subelement and the overflow properties of the &lt;code&gt;.modules-list&lt;/code&gt; subelement. Lastly, the &lt;code&gt;.ph-jhlite-modules-sidemenu&lt;/code&gt; class manages the flexbox properties of the side menu, and manipulates the height and flexbox properties of its &lt;code&gt;-top&lt;/code&gt; and &lt;code&gt;-bottom&lt;/code&gt; subelements.&lt;/p&gt;

&lt;p&gt;Basically, this SCSS mimics the positions of the elements from the ModulePatch screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step VII: modules-patch-loader/ModulesPatchLoader.html
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ModulesPatchLoader.html&lt;/code&gt; is an HTML file that serves as a template for a Vue.js component. It sets up the structure of the component and uses Vue.js directives to create dynamic logic, like loops (&lt;code&gt;v-for&lt;/code&gt;) and class bindings (&lt;code&gt;:class&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;div class="jhlite-modules-loader-content jhlite-menu-content-template" data-selector="modules-loader"&amp;gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-jhlite-modules-container-content jhlite-menu-content-template--content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modules-filter"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12 big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modules-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-row"&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(row, index) in rows"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"`ph-col-${col.size} ${col.classes}`"&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(col, index) in row.columns"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhlite-menu-content-template--menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-jhlite-modules-sidemenu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-jhlite-modules-sidemenu-top"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12 empty"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-6 big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-6 empty big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12 empty"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-6"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-6 empty"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12 big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-10"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-10 empty"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-jhlite-modules-sidemenu-bottom"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12 big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-col-12 big"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go through the given code line by line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhlite-modules-loader-content jhlite-menu-content-template"&lt;/span&gt; &lt;span class="na"&gt;data-selector=&lt;/span&gt;&lt;span class="s"&gt;"modules-loader"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, a &lt;code&gt;div&lt;/code&gt; is defined with the class &lt;code&gt;jhlite-modules-loader-content jhlite-menu-content-template&lt;/code&gt; and a data-selector attribute &lt;code&gt;modules-loader&lt;/code&gt;. This serves as the root container for the module loader.&lt;/p&gt;

&lt;p&gt;The next section is a container for the content of the modules. This is where the dynamic creation of the modules happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-jhlite-modules-container-content jhlite-menu-content-template--content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The nested &lt;code&gt;div&lt;/code&gt; elements provide structure and design to the modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modules-filter"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"modules-list"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the &lt;code&gt;modules-list&lt;/code&gt; section, a Vue.js directive &lt;code&gt;v-for&lt;/code&gt; is used to loop over an array &lt;code&gt;rows&lt;/code&gt;. Each row in this array represents a row in the module list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-row"&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(row, index) in rows"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside each row, another &lt;code&gt;v-for&lt;/code&gt; directive is used to iterate over the columns in the row. The class of the column is dynamically bound with the Vue.js &lt;code&gt;:class&lt;/code&gt; directive, which allows different styling based on the properties of the &lt;code&gt;col&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"`ph-col-${col.size} ${col.classes}`"&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(col, index) in row.columns"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final section defines a side menu, which is broken down into a top and bottom section. Each of these sections contains several rows and columns for displaying information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"jhlite-menu-content-template--menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-jhlite-modules-sidemenu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-jhlite-modules-sidemenu-top"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ph-jhlite-modules-sidemenu-bottom"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    ...
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step VIII: modules-patch-loader/ModulesPatchLoader.component.ts
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ModulesPatchLoader.component.ts&lt;/code&gt; is a TypeScript file that exports a Vue.js component, which includes a &lt;code&gt;setup&lt;/code&gt; function for creating reactive data. Additionally, several helper functions are used to generate columns and rows for the component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ModulesPatchLoaderVue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;createCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createCategory&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="nf"&gt;createCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createCategory&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="nf"&gt;createCategory&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="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCategory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modulesCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;createBigColumn&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="nf"&gt;createBigColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createNormalEmptyColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createBigColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;additionalColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modulesCount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;createBigColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastColumn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createBigColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createRow&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;baseColumns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;additionalColumns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastColumn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createColumn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;classes&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createBigColumn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isEmpty&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;empty &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;big`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createNormalEmptyColumn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;empty&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;columns&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below is the breakdown of the code:&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;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ModulesPatchLoaderVue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;createCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createCategory&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="nf"&gt;createCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createCategory&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="nf"&gt;createCategory&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="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this section, the Vue.js component named &lt;code&gt;ModulesPatchLoaderVue&lt;/code&gt; is defined using the &lt;code&gt;defineComponent&lt;/code&gt; function from Vue. The &lt;code&gt;setup&lt;/code&gt; function returns an object with a &lt;code&gt;rows&lt;/code&gt; property. This property holds an array, each element of which is the result of the &lt;code&gt;createCategory&lt;/code&gt; function with different arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createCategory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modulesCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;createBigColumn&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="nf"&gt;createBigColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createNormalEmptyColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;createBigColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;additionalColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modulesCount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;createBigColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastColumn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createBigColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createRow&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;baseColumns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;additionalColumns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastColumn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;createCategory&lt;/code&gt; is a function that takes a &lt;code&gt;modulesCount&lt;/code&gt; argument. It creates an array of &lt;code&gt;baseColumns&lt;/code&gt; and another array of &lt;code&gt;additionalColumns&lt;/code&gt; which holds several &lt;code&gt;createBigColumn&lt;/code&gt; instances based on the &lt;code&gt;modulesCount&lt;/code&gt;. It then combines these arrays into a single row using the &lt;code&gt;createRow&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createColumn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;classes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;classes&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createBigColumn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isEmpty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;isEmpty&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;empty &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;big`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createNormalEmptyColumn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;createColumn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;empty&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;createColumn&lt;/code&gt;, &lt;code&gt;createBigColumn&lt;/code&gt;, and &lt;code&gt;createNormalEmptyColumn&lt;/code&gt; are helper functions used for creating different types of columns. &lt;code&gt;createColumn&lt;/code&gt; function creates a column object with &lt;code&gt;size&lt;/code&gt; and &lt;code&gt;classes&lt;/code&gt; properties. &lt;code&gt;createBigColumn&lt;/code&gt; calls &lt;code&gt;createColumn&lt;/code&gt; and adds a 'big' class string to it, optionally marking it as 'empty' based on the &lt;code&gt;isEmpty&lt;/code&gt; argument. &lt;code&gt;createNormalEmptyColumn&lt;/code&gt; creates an 'empty' column with a specified size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createRow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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;columns&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, &lt;code&gt;createRow&lt;/code&gt; is a function that takes an arbitrary number of column objects and wraps them into a single row object.&lt;/p&gt;

&lt;p&gt;By implementing placeholder loading in this way, we significantly enhance the user experience, providing immediate visual feedback while the real content is loading.&lt;/p&gt;

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

&lt;p&gt;Whether you're building a simple blog or a complex web application, incorporating placeholder loading in your Vue.js applications can greatly improve user experience by providing immediate feedback during content loading. The &lt;code&gt;placeholder-loading&lt;/code&gt; library is a flexible, easy-to-use tool for implementing this technique, as demonstrated by the pull request example.&lt;/p&gt;

&lt;p&gt;I hope this post has shed light on the importance of placeholder loading 💡 and how to use the &lt;code&gt;placeholder-loading&lt;/code&gt; library in your Vue.js applications. I hope you enjoyed this insightful guide 📖 on implementing Vue placeholder loading! To continue the conversation, I'd love to hear from you 🗣️.&lt;/p&gt;

&lt;p&gt;Do you have experience using the placeholder-loading library in your own Vue.js applications? How has it improved the user experience? 👥 Or maybe you've faced challenges while implementing this technique, and you're seeking solutions or alternative methods. Share your stories 📚, ask your questions ❓, and let's learn together 🤝!&lt;/p&gt;

&lt;p&gt;Drop your thoughts 💭 in the comment section below and let's foster a healthy discussion around enhancing user experiences in web development. Looking forward to your valuable input! 🌟&lt;/p&gt;

&lt;p&gt;Lastly, let me extend an invitation to join me on my journey 🚀 in the realm of software development. I share my insights, experiences, and valuable resources on Twitter &lt;a href="https://www.twitter.com/renan_afranca" rel="noopener noreferrer"&gt;@renan_afranca&lt;/a&gt; 🐦 and &lt;a href="https://www.linkedin.com/in/renan-af" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; 📎. Following me on these platforms not only keeps you updated on my latest posts and projects 📬 but also opens doors to vibrant discussions and learning opportunities. I look forward to connecting with you! 💼&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥🚀 Ready to level up your coding skills and knowledge? 🚀🔥
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;🚀 &lt;strong&gt;&lt;a href="https://renanfranca.github.io/stepping-into-vue-enhancing-the-user-experience-in-jhipster-lite.html" rel="noopener noreferrer"&gt;Stepping into Vue - Enhancing the User Experience in JHipster Lite&lt;/a&gt;:&lt;/strong&gt; Take a deep dive into the world of Vue and JHipster Lite and uncover ways to significantly uplift the user experience. Whether you're a developer seeking to boost your skills 🛠️, or a tech enthusiast intrigued by the potential of Vue, this post offers compelling insights that you simply can't afford to miss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;💰 &lt;strong&gt;&lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html" rel="noopener noreferrer"&gt;How did I earn money to fix an issue from an Open Source Software (OSS)?&lt;/a&gt;&lt;/strong&gt; Ever wondered if you can turn your passion for OSS into a revenue stream? This riveting post details one coder's journey to monetize their expertise, offering valuable tips, techniques, and motivation for anyone looking to follow a similar path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🌐 &lt;strong&gt;&lt;a href="https://renanfranca.github.io/deploy-jhipster-monolithic-angularjs-and-spring-boot-at-fly.io.html" rel="noopener noreferrer"&gt;Deploy jhipster monolithic (angular + spring boot) at fly.io for FREE&lt;/a&gt;:&lt;/strong&gt; Looking for ways to deploy your jhipster monolithic application at no cost? Discover a step-by-step guide to utilizing fly.io for exactly this. Packed with useful advice, this post is a goldmine for any developer looking to deploy efficiently and effectively, all while keeping costs at bay.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Don't let this opportunity pass you by! Dive in now and unleash the wealth of knowledge these posts have to offer.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Stepping into Vue - Enhancing the User Experience in JHipster Lite</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Thu, 15 Jun 2023 11:48:32 +0000</pubDate>
      <link>https://dev.to/renanfranca/stepping-into-vue-enhancing-the-user-experience-in-jhipster-lite-31an</link>
      <guid>https://dev.to/renanfranca/stepping-into-vue-enhancing-the-user-experience-in-jhipster-lite-31an</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/stepping-into-vue-enhancing-the-user-experience-in-jhipster-lite.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Greetings everyone! Today I'm thrilled to delve into my recent adventure into the world of Vue.js while working on the &lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html#learn-about-the-jhipster-lite-project"&gt;JHipster Lite&lt;/a&gt; project on GitHub. I took the plunge into this popular JavaScript framework to solve an issue, and in the process, learned a great deal about the framework and Hexagonal Architecture. So, let's dive right in!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Issue at Hand
&lt;/h2&gt;

&lt;p&gt;Firstly, I would like to address the problem that kick-started my Vue journey. The &lt;a href="https://github.com/jhipster/jhipster-lite/issues/3371"&gt;Issue #3371&lt;/a&gt; describes that module properties were resetting every time a user navigated to another page. This could prove tiresome for users as they would need to redefine their preferences every time they switched pages. This proposed solution was to persist the module properties across pages using local storage.&lt;/p&gt;

&lt;p&gt;So the issue will be considered fixed when a property typed at the Landscape screen will be loaded at the Patch screen without the need to type it again. Let's take a look at the images below that show the same property 'Project full name' shared between the Landscape and the Patch menu options.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WtV5y9kE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://renanfranca.github.io/img/stepping-into-vue/landscape-module-property.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WtV5y9kE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://renanfranca.github.io/img/stepping-into-vue/landscape-module-property.jpg" alt="image" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;
Landscape screen has the property 'My Super App' highlighted with a blue rectangle 



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fHRxen-6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://renanfranca.github.io/img/stepping-into-vue/patch-module-property.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fHRxen-6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://renanfranca.github.io/img/stepping-into-vue/patch-module-property.jpg" alt="image" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;
Patch screen has the same property 'My Super App' highlighted with a blue rectangle load automatically



&lt;h2&gt;
  
  
  My First Steps with Vue
&lt;/h2&gt;

&lt;p&gt;To address this issue, I found myself working with Vue.js for the first time. I embarked on this journey while creating the &lt;a href="https://github.com/jhipster/jhipster-lite/pull/6091"&gt;Pull Request #6091&lt;/a&gt;, titled "Share module properties between landscape and patch screens". I made numerous code changes to enable the module properties to be shared between screens.&lt;/p&gt;

&lt;p&gt;My first foray into Vue was both exciting and challenging. Vue's reactivity model and component architecture were different from what I was used to, but I quickly found them to be powerful tools for creating interactive user interfaces. I learned how to use Vue directives, computed properties, and component lifecycle hooks to create responsive and efficient components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hexagonal Architecture Challenges
&lt;/h2&gt;

&lt;p&gt;An interesting challenge I faced during this development was maintaining the principles of &lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html#study-hexagonal-architecture"&gt;Hexagonal Architecture&lt;/a&gt; while programming the front-end. There were instances where I made mistakes that contradicted the architectural concepts, but I was fortunate to have a code reviewer who pointed out these discrepancies and clearly guided me on what should be done.&lt;/p&gt;

&lt;p&gt;I have come to appreciate the value of Hexagonal Architecture in isolating the application's core logic from external concerns. The experience also underscored the importance of clear and open communication in collaborative development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making Improvements
&lt;/h2&gt;

&lt;p&gt;The following changes have significantly improved the user experience by maintaining the state of module properties across different pages. The use of a repository for managing module parameters has also enhanced the efficiency and reliability of the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part I: ModuleParametersRepository.ts and LocalStorageModuleParametersRepository.ts
&lt;/h3&gt;

&lt;p&gt;I created two TypeScript files: &lt;code&gt;ModuleParametersRepository.ts&lt;/code&gt; and &lt;code&gt;LocalStorageModuleParametersRepository.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;ModuleParametersRepository.ts&lt;/code&gt;, I introduced an interface &lt;code&gt;ModuleParametersRepository&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ModuleParameterType&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;@/module/domain/ModuleParameters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ModuleParametersRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModuleParameterType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModuleParameterType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This interface provides a contract for storing and retrieving module parameters. The &lt;code&gt;store&lt;/code&gt; method accepts a map of type &lt;code&gt;ModuleParameterType&lt;/code&gt; and doesn't return anything, while the &lt;code&gt;get&lt;/code&gt; method returns a map of the same type.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;LocalStorageModuleParametersRepository.ts&lt;/code&gt;, I implemented the &lt;code&gt;ModuleParametersRepository&lt;/code&gt; interface:&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;ModuleParametersRepository&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;../domain/ModuleParametersRepository&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;ModuleParameterType&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;../domain/ModuleParameters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;LocalStorageModuleParametersRepository&lt;/span&gt;
  &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ModuleParametersRepository&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;STORAGE_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;moduleParameters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Storage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Storage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModuleParameterType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STORAGE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModuleParameterType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storedValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STORAGE_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storedValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storedValue&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ModuleParameterType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this class, I defined a &lt;code&gt;STORAGE_KEY&lt;/code&gt; constant for identifying the storage location and a &lt;code&gt;localStorage&lt;/code&gt; property of type &lt;code&gt;Storage&lt;/code&gt;. The constructor accepts a &lt;code&gt;Storage&lt;/code&gt; object and assigns it to &lt;code&gt;localStorage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;store&lt;/code&gt; method takes a map of &lt;code&gt;ModuleParameterType&lt;/code&gt;, converts it into a string using &lt;code&gt;JSON.stringify&lt;/code&gt;, and stores this string in &lt;code&gt;localStorage&lt;/code&gt; using the &lt;code&gt;setItem&lt;/code&gt; method. The &lt;code&gt;get&lt;/code&gt; method retrieves the stored string from &lt;code&gt;localStorage&lt;/code&gt; using the &lt;code&gt;getItem&lt;/code&gt; method, parses it back into a map using &lt;code&gt;JSON.parse&lt;/code&gt;, and returns it. If no stored value is found, it returns a new, empty map.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part II: Main.ts
&lt;/h3&gt;

&lt;p&gt;The first change I made was to add a new import at the top of the &lt;code&gt;main.ts&lt;/code&gt; file. I imported the &lt;code&gt;LocalStorageModuleParametersRepository&lt;/code&gt; class from the './module/secondary/LocalStorageModuleParametersRepository' file. This class is responsible for storing the module properties in the browser's local storage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LocalStorageModuleParametersRepository&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;./module/secondary/LocalStorageModuleParametersRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I created a new instance of &lt;code&gt;LocalStorageModuleParametersRepository&lt;/code&gt;, passing &lt;code&gt;localStorage&lt;/code&gt; as an argument. This allows the class to access the browser's local storage to store and retrieve the module properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moduleParametersRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;LocalStorageModuleParametersRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, I added &lt;code&gt;moduleParametersRepository&lt;/code&gt; to the Vue application context. This allows any Vue component to access the repository and, therefore, the module properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;moduleParameters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;moduleParametersRepository&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These changes allow module properties to be persistently stored, improving the user experience when navigating between pages. Moreover, the implementation of &lt;code&gt;LocalStorageModuleParametersRepository&lt;/code&gt; allows other parts of the application to easily access the module properties, making the code more modular and easier to maintain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part III: Landscape.component.ts
&lt;/h3&gt;

&lt;p&gt;In the recent update to the Landscape component of the JHipster Lite project, a significant change was made to improve the management of module parameters. The original code used a local reference, &lt;code&gt;valuatedModuleParameters&lt;/code&gt;, to store the parameters of the modules. This was replaced with a more robust solution: a repository pattern.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ModuleParametersRepository&lt;/code&gt; was imported at the top of the file, and an instance of it was injected into the component. This repository is responsible for managing the module parameters, providing a more centralized and consistent way to handle these values. This change can be seen in the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ModuleParametersRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/module/domain/ModuleParametersRepository&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moduleParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;moduleParameters&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ModuleParametersRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moduleParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;moduleParametersValues&lt;/code&gt; reference now points to the values retrieved from the repository, and any changes to these values are stored back into the repository. This can be seen in the &lt;code&gt;updateProperty&lt;/code&gt; and &lt;code&gt;deleteProperty&lt;/code&gt; methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateProperty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModuleParameter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;moduleParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deleteProperty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;moduleParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This new approach ensures that the module parameters are consistently managed across different parts of the application, reducing the risk of inconsistencies and bugs. It also makes the code more maintainable and easier to understand, as the responsibility of managing the module parameters is clearly defined and encapsulated within the &lt;code&gt;ModuleParametersRepository&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part IV: ModulesPatch.component.ts
&lt;/h3&gt;

&lt;p&gt;Starting with the import section, I introduced &lt;code&gt;ModuleParametersRepository&lt;/code&gt; from the domain of the module. This repository is designed to manage the module parameters, providing a more efficient way to handle them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ModuleParametersRepository&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;@/module/domain/ModuleParametersRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;defineComponent&lt;/code&gt; function, I replaced the &lt;code&gt;moduleParameters&lt;/code&gt; ref with an injection of &lt;code&gt;moduleParameters&lt;/code&gt; from the &lt;code&gt;ModuleParametersRepository&lt;/code&gt;. This allows the component to directly access the repository, improving the efficiency of data retrieval. I also introduced &lt;code&gt;moduleParametersValues&lt;/code&gt; as a ref, which gets the current state of the module parameters from the repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moduleParameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;moduleParameters&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ModuleParametersRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moduleParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;isNotSet&lt;/code&gt; function, I changed the source of the value from &lt;code&gt;moduleParameters.value.get(propertyKey)&lt;/code&gt; to &lt;code&gt;moduleParametersValues.value.get(propertyKey)&lt;/code&gt;. This ensures that the function checks the current state of the module parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;propertyKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;updateProperty&lt;/code&gt; and &lt;code&gt;deleteProperty&lt;/code&gt; functions, I updated the state of the module parameters in the repository after every change. This ensures that the repository always holds the most recent state of the module parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateProperty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModuleParameter&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;moduleParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deleteProperty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ModulePropertyKey&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;moduleParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the function that applies a module, I replaced &lt;code&gt;moduleParameters.value&lt;/code&gt; with &lt;code&gt;moduleParametersValues.value&lt;/code&gt; as the source of parameters. This ensures that the most recent state of the module parameters is used when applying a module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the function that handles project history properties, I updated the state of the module parameters in the repository after setting each unknown property. This ensures that the repository is updated with any new properties that are discovered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;moduleParameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, in the return statement of the &lt;code&gt;defineComponent&lt;/code&gt; function, I replaced &lt;code&gt;moduleParameters&lt;/code&gt; with &lt;code&gt;moduleParametersValues&lt;/code&gt;. This ensures that the component always provides the most recent state of the module parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;moduleParametersValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;These changes have the potential to significantly enhance the user experience in JHipster Lite. With the module properties now persisting across pages, users no longer need to redefine their preferences every time they navigate to a different page.&lt;/p&gt;

&lt;p&gt;However, please note that these changes generated the following bug &lt;a href="https://github.com/jhipster/jhipster-lite/issues/6279"&gt;Local properties storage do no reset #6279&lt;/a&gt; which I have already fixed it. I eagerly look forward to feedback from the community and I am ready to make any necessary adjustments.&lt;/p&gt;

&lt;p&gt;For a comprehensive understanding of the changes, I recommend reviewing the code directly on GitHub. Stay tuned for more updates on JHipster Lite's development!&lt;/p&gt;

&lt;p&gt;That's it for now, folks! I hope you've enjoyed my journey into Vue.js, the challenges of Hexagonal Architecture, and the solutions I've implemented to improve JHipster Lite's user experience. The software development world is full of exciting challenges and adventures, and I would be more than happy to have you follow along with me.&lt;/p&gt;

&lt;p&gt;If you want to stay updated with my latest projects and insights, follow me on Twitter at &lt;a href="https://www.twitter.com/renan_afranca"&gt;@renan_afranca&lt;/a&gt; and connect with me on LinkedIn at &lt;a href="https://www.linkedin.com/in/renan-af"&gt;https://www.linkedin.com/in/renan-af&lt;/a&gt;. Let's explore this tech-filled universe together!&lt;/p&gt;

&lt;p&gt;I'd love to hear your thoughts on our exploration of Vue.js and Hexagonal Architecture. How could these principles be applied to your projects? Is there another JavaScript framework you're considering using with Hexagonal Architecture?&lt;/p&gt;

&lt;p&gt;Your input is incredibly valuable. Please share your thoughts in the comments below. Your insights will contribute significantly to our ongoing discussion and learning. I'm looking forward to hearing from you! Happy coding!&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Ignite Your Coding Journey
&lt;/h2&gt;

&lt;p&gt;💰 Want to get started in open source software and turn your technical skills into earnings? Don't miss out on reading &lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html"&gt;How did I earn money to fix an issue from an Open Source Software (OSS)?&lt;/a&gt; It's full of practical tips and real-life experiences that could set you on your own path to financial success. Dive into the world of OSS today and start making a difference while earning money!&lt;/p&gt;

&lt;p&gt;🚀 Interested in deploying a powerful combination of Angular and Spring Boot but concerned about the cost? Fret not! &lt;a href="https://renanfranca.github.io/deploy-jhipster-monolithic-angularjs-and-spring-boot-at-fly.io.html"&gt;Deploy jhipster monolithic (angular + spring boot) at fly.io for FREE&lt;/a&gt; is what you need. Discover how to harness the power of jhipster and deploy your app at zero cost on fly.io. Get your app up and running without breaking the bank.&lt;/p&gt;

&lt;p&gt;📱 Get ready to revolutionize your coding experience! &lt;a href="https://renanfranca.github.io/2022/03/02/vscode-on-android.html"&gt;VSCode on Android (you don’t need to install anything)&lt;/a&gt; is a game-changer. Experience VSCode on your Android device without the hassle of installing any additional software. Stay connected and code on the go. Unleash the power of mobile coding today!&lt;/p&gt;

&lt;p&gt;Don't let this opportunity pass you by! Dive in now and unleash the wealth of knowledge these posts have to offer.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How did I earn money to fix an issue from an Open Source Software (OSS)?</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Mon, 06 Feb 2023 11:33:22 +0000</pubDate>
      <link>https://dev.to/renanfranca/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software-oss-4kfm</link>
      <guid>https://dev.to/renanfranca/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software-oss-4kfm</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/how-did-i-earn-money-to-fix-an-issue-from-an-open-source-software.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I am going to share my approach and my own experience and opinion about fixing a bounty issue from the &lt;a href="https://github.com/jhipster/jhipster-lite"&gt;jhipster-lite Open Source Software (OSS)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wich issue to choose
&lt;/h2&gt;

&lt;p&gt;I got stuck for a long time because I couldn't decide which issue I should fix and I didn't have much time to spend fixing an issue. I could only be coding while my baby girl was sleeping.&lt;/p&gt;

&lt;p&gt;At first, I created &lt;a href="https://github.com/jhipster/jhipster-lite/issues/4401"&gt;an issue to fix&lt;/a&gt; because I was afraid to fail to fix an existing issue. Then I realized that isn't a good idea to implement a front-end feature because my strength is back-end code using spring boot!&lt;/p&gt;

&lt;p&gt;After some time, I decided to join together my goal to help the jhipster-lite (jhlite) project by solving an issue with my need to earn money beyond my paycheck. So I started to read the &lt;a href="https://github.com/jhipster/jhipster-lite/labels/%24%24%20bug-bounty%20%24%24"&gt;bounty issues list&lt;/a&gt;, looking for an issue that demands only backend skills to fix.&lt;/p&gt;

&lt;p&gt;In the end, I decided to try to fix this issue: &lt;a href="https://github.com/jhipster/jhipster-lite/issues/2106"&gt;Add the possibility to comment spring properties in modules&lt;br&gt;
&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How should I start to fix an issue?
&lt;/h2&gt;

&lt;p&gt;I started to read the closed issues to understand and look for answers to my questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How an issue was assigned to someone?&lt;/li&gt;
&lt;li&gt;Should I ask for permission to fix it before I start to try to fix it?&lt;/li&gt;
&lt;li&gt;What happens if two contributors were trying to fix the same issue and both didn't ask for permission?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I found all the answers in the &lt;a href="https://www.jhipster.tech/bug-bounties/#how-to-get-the-money"&gt;bounty issue instructions&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Create a Pull Request that fixes a ticket with the &lt;code&gt;$$ bug-bounty $$&lt;/code&gt; label.&lt;/li&gt;
&lt;li&gt;In order to close the ticket automatically, you must have one commit message with the &lt;code&gt;Fix&lt;/code&gt; keyword. For example, &lt;code&gt;Fix #1234&lt;/code&gt; to close ticket &lt;code&gt;#1234&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;That Pull Request must be merged by someone from the core team. If there are several Pull Requests, the core team member either selects the most recent one or the best one - that’s up to the team member to decide what is best for the project.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;In addition, I realized that I was afraid of getting my attempt to fix declined by the reviewer. So I decided to walk over my fear and try to fix and create a pull request as fast as possible to gather feedback (positive or negative) from the reviewer.&lt;/p&gt;
&lt;h2&gt;
  
  
  What did help me to fix the issue?
&lt;/h2&gt;

&lt;p&gt;Here I will try to share some of my abilities and background knowledge which gives me the confidence to keep up coding until the issue got merged 😄!&lt;/p&gt;
&lt;h3&gt;
  
  
  Learn about the jhipster-lite project
&lt;/h3&gt;

&lt;p&gt;In my case, I need to understand the project to be motivated to contribute to it. Below, I will list some interesting resources to fall in love with jhlite 😊.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.jhipster.tech/jhipster-lite/"&gt;What is JHipster Lite?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Read everything at the jhipster-lite &lt;a href="https://github.com/jhipster/jhipster-lite/blob/main/CONTRIBUTING.md"&gt;contributing guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=dTzGQNOKWug"&gt;What is JHipster Lite and why should you care?&lt;/a&gt; by &lt;a href="https://twitter.com/juliendubois"&gt;Julien Dubois&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Excelente content showing how to use jhipster-lite and Julien will guide you through jhlite options. In the end, you will create the demo project and could explore it by yourself! That was so cool!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=O-P58uCWrfI"&gt;How to contribute to JHipster&lt;/a&gt; by &lt;a href="https://twitter.com/avdev4j"&gt;Anthony Viard&lt;/a&gt; and &lt;a href="https://twitter.com/TheSohini"&gt;Sohini Pattanayak&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;I learn a lot of tricks with this video which covers how to contribute to jhipster-lite, for example, name my branch using the GitHub issue number &lt;code&gt;2106-add-comment-spring-properties-in-modules&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=mEECPRZjajI"&gt;Simple WebServices with JHipster Lite&lt;/a&gt; by &lt;a href="https://www.linkedin.com/in/colin-damon/"&gt;Colin Damon&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Here you will learn how jhipster lite could be your best friend in coding! This great demo was made by the reviewer of my pull request. "Hi! Colin 👋!".&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Study Hexagonal Architecture
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jhipster/jhipster-lite/blob/main/documentation/hexagonal-architecture.md"&gt;Hexagonal architecture (application service flavor)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;I cloned the jhipster-lite project and run it in debug mode to learn more about the code base which I am going to change.&lt;/li&gt;
&lt;li&gt;Then I realized that a better approach is to run the implemented tests in debug mode. The test works as a documentation of the functionalities.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Affinity and joy in implementing Tests
&lt;/h3&gt;

&lt;p&gt;I believe that implementing tests is the way to build great software. The jhipster-lite project is configured to accept only 100% test coverage code. So any change made in this project needs to be tested!&lt;/p&gt;

&lt;p&gt;The test code should be as good as the production code, that's not a trivial task. In my opinion, the jhlite project has a high-quality code base and I had to do my best to implement a feature with the best code I could make.&lt;/p&gt;
&lt;h3&gt;
  
  
  Know in advance some technologies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Maven&lt;/li&gt;
&lt;li&gt;Java

&lt;ul&gt;
&lt;li&gt;Jacoco&lt;/li&gt;
&lt;li&gt;Cucumber&lt;/li&gt;
&lt;li&gt;JUnit&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Spring Boot&lt;/li&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;li&gt;Prettier&lt;/li&gt;
&lt;li&gt;Sonar&lt;/li&gt;
&lt;li&gt;Git (especially rebase commands)&lt;/li&gt;
&lt;li&gt;GitHub (Actions (CI), Fork, Issues, and Create Pull Request)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  My workflow
&lt;/h2&gt;

&lt;p&gt;I will share my workflow which I used to fix, improve, and refactor the code each time my pull request was reviewed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Before pushing my changes to be reviewed
&lt;/h3&gt;

&lt;p&gt;Here is the script I used to keep my branch up to date with the latest version of the jhipster-lite main branch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch main
git fetch upstream
git rebase upstream/main
git push
git switch &amp;lt;my-branch-name&amp;gt;
git rebase origin/main
npm run prettier:format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I run the sonar after I finished coding.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; src/main/docker/sonar.yml up &lt;span class="nt"&gt;-d&lt;/span&gt;
./mvnw clean verify sonar:sonar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So you can check the result at &lt;code&gt;http://localhost:9001&lt;/code&gt; to see if you match the 100% code coverage or if you need to fix any code smells.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep the pull request reviewer informed
&lt;/h3&gt;

&lt;p&gt;Every time I pushed some changes I let the reviewer know and I always answers each code review he made.&lt;/p&gt;

&lt;p&gt;I preferred to push the changes even though I didn't fully understand what the review wants because in my experience is easier to talk about an implemented code than a hypothetical one.&lt;/p&gt;

&lt;p&gt;There is a &lt;a href="https://github.com/jhipster/jhipster-lite/blob/main/CODE_OF_CONDUCT.md"&gt;Contributor Covenant Code of Conduct&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In my own experience as a contributor, I can say that everyone who I interacted with was kind and genuinely wants the best for the project. I felt that they appreciate my effort to fix an issue and they were cheering me up!&lt;/p&gt;

&lt;h3&gt;
  
  
  Claim the bounty
&lt;/h3&gt;

&lt;p&gt;After my pull request got merged, I was eligible to claim the bounty.&lt;/p&gt;

&lt;p&gt;First, I create an invoice at open collective: &lt;a href="https://opencollective.com/generator-jhipster/expenses/117514"&gt;$300 bug bounty claim for https://github.com/jhipster/jhipster-lite/pull/4814&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then I published the invoice link at my pull request: &lt;a href="https://github.com/jhipster/jhipster-lite/pull/4814#issuecomment-1374433366"&gt;https://github.com/jhipster/jhipster-lite/pull/4814#issuecomment-1374433366&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After some time, the invoice was processed and I got paid 👏😃☺️!&lt;/p&gt;

&lt;p&gt;The official documentation explains each step to claim your bounty: &lt;a href="https://www.jhipster.tech/bug-bounties/#how-to-get-the-money"&gt;How to get the money&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What was the outcome of this experience?
&lt;/h2&gt;

&lt;p&gt;I am a Windows user, but I am migrating to use Linux (Ubuntu) through wsl 2 because It is faster. On windows took me 5 minutes and 20 seconds to run the command &lt;code&gt;./mvnw clean verify sonar:sonar&lt;/code&gt;. On Linux, the same command took me 2 minutes and 30 seconds. I found this great YouTube video &lt;a href="https://youtu.be/bRW5r7TK6KM"&gt;How To Run Linux Code on Windows with WSL 2 &amp;amp; VS Code&lt;/a&gt; which taught me how to use Linux for coding inside Windows. In addition, my developer experience was lighter and smoothly with VS Code running under Linux.&lt;/p&gt;

&lt;p&gt;I enjoyed working on the jhlite project without being pressured and asynchronously! I could code when I have the time on my own passe 👏!&lt;/p&gt;

&lt;p&gt;I realized that I am not an expert in the TDD field, I have so much to learn. Here is an interesting article that opens my eyes &lt;a href="https://www.codecraftr.nl/why-use-tdd"&gt;The Real Reasons for Doing Test-Driven Development&lt;/a&gt;. Thanks to &lt;a href="https://www.linkedin.com/in/colin-damon/"&gt;Colin Damon&lt;/a&gt; for letting me know that I was doing Test First and not TDD and for introducing the concept of &lt;a href="https://manifesto.softwarecraftsmanship.org/"&gt;Software Craftsmanship&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://twitter.com/pascalgrimaud"&gt;Pascal Grimaud&lt;/a&gt; for being around and following along on the issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  What next
&lt;/h2&gt;

&lt;p&gt;I am planning to continue to contribute to the jhlite project by fixing issues and keep writing blog posts about my experience with jhipster.&lt;/p&gt;

&lt;p&gt;One day, I wish to be part of the &lt;a href="https://www.jhipster.tech/team/"&gt;jhipster core team&lt;/a&gt; 😊!&lt;/p&gt;

</description>
      <category>jhipster</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Learn to debug the JHipster generator, increase your chances to fix bounty issues</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Mon, 30 Jan 2023 10:22:47 +0000</pubDate>
      <link>https://dev.to/renanfranca/learn-to-debug-the-jhipster-generator-increase-your-chances-to-fix-bounty-issues-133h</link>
      <guid>https://dev.to/renanfranca/learn-to-debug-the-jhipster-generator-increase-your-chances-to-fix-bounty-issues-133h</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/learn-debug-jhipster-generator-increase-your-chances-to-fix-bounty-issues.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;You can earn money by fixing issues with bounty labels!&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--IsRWFYFg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1268019296879476736/RoM1BG4W_normal.jpg" alt="Matt Raible profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Matt Raible
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/mraible"&gt;@mraible&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Want to make some money doing open source @Java development? There's over $2500 USD available for fixing issues in the @JHipster + &lt;a href="https://twitter.com/QuarkusIO"&gt;@QuarkusIO&lt;/a&gt; blueprint!&lt;br&gt;&lt;br&gt;💰 &lt;a href="https://t.co/p80VRNrGw0"&gt;github.com/jhipster/gener…&lt;/a&gt;&lt;br&gt;&lt;br&gt;See our bug bounty program for more info: &lt;a href="https://t.co/PBURlaaqhg"&gt;jhipster.tech/bug-bounties/&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;a href="https://twitter.com/hashtag/java"&gt;#java&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/jhipster"&gt;#jhipster&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/opensource"&gt;#opensource&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      12:08 PM - 21 Sep 2021
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1440286692049522690" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1440286692049522690" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1440286692049522690" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;p&gt;Take a look at the available &lt;a href="https://github.com/jhipster/generator-jhipster/issues?q=is%3Aissue+is%3Aopen+label%3A%22%24%24+bug-bounty+%24%24%22"&gt;bounty issues&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands on
&lt;/h2&gt;

&lt;p&gt;Here I will show you how to debug the jhipster import-jdl command with an inline entity example. I am using VSCode with Windows 10.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jhipster import-jdl &lt;span class="nt"&gt;--inline&lt;/span&gt; &lt;span class="s1"&gt;'entity RenanClass(RenanTable) { testString String }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;First clone the generator-jhipster into a folder, and follow the instructions below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md#set-npm-to-use-the-cloned-project"&gt;&lt;strong&gt;&lt;em&gt;Set NPM to use the cloned project&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then open the generator-jhipster root folder and your VSCode will look like that:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6VhPRjrC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-generator-folder.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6VhPRjrC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-generator-folder.png" alt="image" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;
VSCode with generator-jhipster folder


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click at the bottom to change the Auto Attach to &lt;a href="https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_auto-attach"&gt;Smart&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on Debug icon (left) :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sxRD2fWS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-debug-view.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sxRD2fWS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-debug-view.png" alt="image" width="880" height="477"&gt;&lt;/a&gt;&lt;/p&gt;
VSCode Debug View



&lt;p&gt;You will see at the top left some debug options. There are many options pre-configured for different commands. Choose the &lt;em&gt;jhipster import-jdl&lt;/em&gt; and click on the setting icon:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iRyUoYPx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-debug-options.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iRyUoYPx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-debug-options.png" alt="image" width="406" height="489"&gt;&lt;/a&gt;&lt;/p&gt;
VSCode JHipster Debug Options


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make a copy of &lt;em&gt;jhipster import-dl&lt;/em&gt; configuration and change it to be like that:&lt;br&gt;
&lt;/p&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CUSTOM jhipster import-jdl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/cli/jhipster.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"args"&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;"import-jdl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
            &lt;/span&gt;&lt;span class="s2"&gt;"--inline"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
            &lt;/span&gt;&lt;span class="s2"&gt;"entity RenanClass(RenanTable) { testString String }"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
            &lt;/span&gt;&lt;span class="s2"&gt;"-d"&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;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/test-integration/samples/app-sample-dev/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"console"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integratedTerminal"&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;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--afPnOfTb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-launch-json.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--afPnOfTb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-launch-json.png" alt="image" width="880" height="478"&gt;&lt;/a&gt;&lt;/p&gt;
VSCode launch.json


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose the new debug option &lt;em&gt;CUSTOM jhipster import-jdl&lt;/em&gt; and hit the play button:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rp8FosSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-run-debug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rp8FosSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/debug-jhipster-generator/vscode-run-debug.png" alt="image" width="351" height="189"&gt;&lt;/a&gt;&lt;/p&gt;
VSCode run Debug


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;My suggestion for your first breakpoint. Open the file &lt;em&gt;cli\jhipster.js&lt;/em&gt; and put the breakpoint at line 50:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (preferLocal) {&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If everything works and you got the execution stopped at the first breakpoint, I will recommend another one. Open file &lt;em&gt;cli\jdl.js&lt;/em&gt; and put the breakpoint at line 48:&lt;/p&gt;

&lt;p&gt;logger.debug(&lt;code&gt;jdlFiles: ${toString(jdlFiles)}&lt;/code&gt;);&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  You could get this failure message
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;PS C:&lt;span class="se"&gt;\U&lt;/span&gt;sers&lt;span class="se"&gt;\R&lt;/span&gt;enan&lt;span class="se"&gt;\D&lt;/span&gt;ocuments&lt;span class="se"&gt;\J&lt;/span&gt;Hipster&lt;span class="se"&gt;\T&lt;/span&gt;UTORIALS&lt;span class="se"&gt;\h&lt;/span&gt;ow_debug_with_vscode&lt;span class="se"&gt;\g&lt;/span&gt;enerator-jhipster&lt;span class="se"&gt;\t&lt;/span&gt;est-integration&lt;span class="se"&gt;\s&lt;/span&gt;amples&lt;span class="se"&gt;\a&lt;/span&gt;pp-sample-dev&amp;gt;  &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;env&lt;/span&gt;:NODE_OPTIONS&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'--require "c:/Users/Renan/AppData/Local/Programs/Microsoft VS Code Insiders/resources/app/extensions/ms-vscode.js-debug/src/bootloader.bundle.js" --inspect-publish-uid=http'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;env&lt;/span&gt;:VSCODE_INSPECTOR_OPTIONS&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{"inspectorIpc":"\\\\.\\pipe\\node-cdp.10508-2.sock","deferredMode":false,"waitForDebugger":"","execPath":"C:\\Program Files\\nodejs\\node.exe","onlyEntrypoint":false,"autoAttachMode":"always","fileCallback":"C:\\Users\\Renan\\AppData\\Local\\Temp\\node-debug-callback-f76952482a888dfe"}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &amp;amp; &lt;span class="s1"&gt;'C:\Program Files\nodejs\node.exe'&lt;/span&gt; &lt;span class="s1"&gt;'.\..\..\..\cli\jhipster.js'&lt;/span&gt; &lt;span class="s1"&gt;'import-jdl'&lt;/span&gt; &lt;span class="s1"&gt;'--inline'&lt;/span&gt; &lt;span class="s1"&gt;'entity RenanClass(RenanTable) { testString String }'&lt;/span&gt; &lt;span class="s1"&gt;'-d'&lt;/span&gt;  
Debugger attached.  
Waiting &lt;span class="k"&gt;for &lt;/span&gt;the debugger to disconnect...  
internal/modules/cjs/loader.js:905  
  throw err&lt;span class="p"&gt;;&lt;/span&gt;  
  ^Error: Cannot find module &lt;span class="s1"&gt;'semver'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;To solve this misconfiguration&lt;/strong&gt; go to generator-jhipster root folder and confirm that you executed the following command:&lt;/p&gt;

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

&lt;p&gt;Then go to the &lt;em&gt;test-integration\samples\app-sample-dev&lt;/em&gt; folder (if you hit the play button again, you are already there). After that, execute this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm link generator-jhipster&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then run this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jhipster --skip-jhipster-dependencies&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, hit the debug button and it will work smoothly =) !&lt;/p&gt;

&lt;h2&gt;
  
  
  That is all. Thank you for your attention
&lt;/h2&gt;

&lt;p&gt;All steps I mentioned above are described at the &lt;a href="https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md#use-a-debugger"&gt;CONTRIBUTING.md&lt;/a&gt;. I’ve never work with node.js, yeoman, and ejs before. Because that, I had to read the instructions over and over again until I figured out how to make it works.&lt;/p&gt;

&lt;p&gt;In my opinion, the &lt;a href="https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md#use-a-debugger"&gt;CONTRIBUTING.md&lt;/a&gt; do the job, but we have to study to understand it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Thank you JHipster!
&lt;/h1&gt;

</description>
      <category>jhipster</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Deploy jhipster monolithic (angular + spring boot) at fly.io for FREE</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Tue, 25 Oct 2022 08:51:01 +0000</pubDate>
      <link>https://dev.to/renanfranca/deploy-jhipster-monolithic-angular-spring-boot-at-flyio-for-free-5dng</link>
      <guid>https://dev.to/renanfranca/deploy-jhipster-monolithic-angular-spring-boot-at-flyio-for-free-5dng</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/deploy-jhipster-monolithic-angularjs-and-spring-boot-at-fly.io.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://renanfranca.github.io/i-built-a-baby-care-web-app-using-jhipster.html"&gt;I built a Baby Care web app&lt;/a&gt; using microservices architecture to challenge me in my roadmap to master &lt;a href="https://renanfranca.github.io/2022/02/24/why-did-i-use-jhipster.html"&gt;jhipster&lt;/a&gt;. Unfortunately turns out that I couldn't afford the cost of &lt;a href="https://renanfranca.github.io/publishing-microservices-into-gke.html"&gt;Publishing Microservices into Google Kubernetes Engine (GKE)&lt;/a&gt; and I decided to self-host the Baby Care App in my notebook and keep accessing it through my phone.&lt;/p&gt;

&lt;p&gt;My baby girl Marília complete 9 months old so we are going out with her and I couldn't access the Baby Care App outside of my home. I decided to rewrite the Baby Care App as a monolithic architecture using jhipster to deploy it on Heroku for free. When I finally rebuilt the app, I realized that &lt;a href="https://techcrunch.com/2022/08/25/heroku-announces-plans-to-eliminate-free-plans-blaming-fraud-and-abuse/?utm_source=tldrnewsletter"&gt;Heroku is going to shut down the free tier plan&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;I will share with you my experience to publish an angular + spring boot + postgres database solution into &lt;a href="https://fly.io"&gt;fly.io&lt;/a&gt; for FREE. I opened source &lt;a href="https://github.com/renanfranca/mamazinha-monolithic/tree/publish-to-flydotio"&gt;the Baby Care App as monolithic&lt;/a&gt; to let you put your hands on the code as I explain the step-by-step:&lt;br&gt;
 &lt;a href="https://github.com/renanfranca/mamazinha-monolithic"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s56-32gY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://renanfranca.github.io/img/mamazinha-baby-care/github-mamazinha-monolithic-image_readme.png" alt="renanfranca/mamazinha-monolithic" width="838" height="200"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create postgres into flyio
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Free tier plan
&lt;/h3&gt;

&lt;p&gt;According to &lt;a href="https://community.fly.io/t/how-to-convert-your-not-free-postgres-to-free-postgres/3888"&gt;this flyio community post&lt;/a&gt;, the free tier is a postgres with 1GB volume attached running in the free tier machine (shared-cpu-1x 256mb VMs).&lt;/p&gt;
&lt;h3&gt;
  
  
  Install flyctl
&lt;/h3&gt;

&lt;p&gt;I am using Windows 10, so I had to run the following command at Powershell &lt;code&gt;iwr https://fly.io/install.ps1 -useb | iex&lt;/code&gt; . Visit &lt;a href="https://fly.io/docs/hands-on/install-flyctl/"&gt;this link&lt;/a&gt; to install it on another OS.&lt;/p&gt;
&lt;h3&gt;
  
  
  Signup
&lt;/h3&gt;

&lt;p&gt;Run the command &lt;code&gt;flyctl auth signup&lt;/code&gt; to create your account. I put my credit card to earn more free resources, &lt;a href="https://fly.io/blog/free-postgres/"&gt;according to the documentation&lt;/a&gt; it's necessary to use postgres for free.&lt;/p&gt;
&lt;h3&gt;
  
  
  Login
&lt;/h3&gt;

&lt;p&gt;Run the command &lt;code&gt;flyctl auth login&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a postgres app
&lt;/h3&gt;

&lt;p&gt;Run the command &lt;code&gt;flyctl postgres create&lt;/code&gt; and I choose the following options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;? Choose an app name (leave blank to generate one): baby-postgres&lt;/li&gt;
&lt;li&gt;automatically selected personal organization: Renan Franca&lt;/li&gt;
&lt;li&gt;? Select regions: São Paulo (gru)&lt;/li&gt;
&lt;li&gt;? Select configuration: Development - Single node, 1x shared CPU, 256MB RAM, 1GB disk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After the postgres app were created you will receive something like that as an output:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Postgres cluster baby-postgres created&lt;/li&gt;
&lt;li&gt;Username:    postgres&lt;/li&gt;
&lt;li&gt;Password:    randompassword&lt;/li&gt;
&lt;li&gt;Hostname:    baby-postgres.internal&lt;/li&gt;
&lt;li&gt;Proxy Port:  5432&lt;/li&gt;
&lt;li&gt;Postgres Port: 5433&lt;/li&gt;
&lt;li&gt;postgres://postgres:&lt;a href="mailto:randompassword@baby-postgres.internal"&gt;randompassword@baby-postgres.internal&lt;/a&gt;:5432&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write it down, because you won't have another chance to access your postgres server information.&lt;br&gt;
Run the following command &lt;code&gt;flyctl volumes list -a baby-postgres&lt;/code&gt; to confirm that a persistent free volume was automatically created for your postgres app.&lt;/p&gt;
&lt;h3&gt;
  
  
  Create the baby database
&lt;/h3&gt;

&lt;p&gt;You will have to connect to the fly.io postgres server that you created to define the databasename. Use this command to port forward and connect with &lt;a href="https://www.pgadmin.org/download/"&gt;pdadmin&lt;/a&gt; locally &lt;code&gt;flyctl proxy 5432 -a &amp;lt;postgres-app-name&amp;gt;&lt;/code&gt;.&lt;br&gt;
Use 127.0.0.1 instead of localhost when defining the host of your connection at pgadmin, because if you use localhost you will get the following error &lt;code&gt;could not receive data from server: Socket is not connected&lt;/code&gt; (&lt;a href="https://serverfault.com/a/1003780/244961"&gt;https://serverfault.com/a/1003780/244961&lt;/a&gt;). In my case, I created the database called baby that will be used by my spring boot application.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create angular + spring boot server
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Free tier plan
&lt;/h3&gt;

&lt;p&gt;According to &lt;a href="https://fly.io/docs/about/pricing/"&gt;this flyio pricing link&lt;/a&gt;, the free tier include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Up to 3 shared-cpu-1x 256mb VMs&lt;/li&gt;
&lt;li&gt;  160GB outbound data transfer&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Create the dockerfile to the baby care app
&lt;/h3&gt;

&lt;p&gt;Let's create the Dockerfile at the root of your project folder to run my jhipster angular+spring boot application. I got out of memory error when I tried to deploy using a regular OpenJDK image. I learned that works if you use an optimized ibm jre (&lt;a href="https://community.fly.io/t/deployment-of-java-spring-api-using-dockerfile/6708/5"&gt;https://community.fly.io/t/deployment-of-java-spring-api-using-dockerfile/6708/5&lt;/a&gt;) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ibm-semeru-runtimes:open-11-jre-focal&lt;/span&gt;
&lt;span class="k"&gt;MAINTAINER&lt;/span&gt;&lt;span class="s"&gt; https://renanfranca.github.io/about.html&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; target/baby-0.0.1-SNAPSHOT.jar baby-0.0.1-SNAPSHOT.jar&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; _JAVA_OPTIONS="-XX:MaxRAM=70m"&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; java $_JAVA_OPTIONS -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE -Dspring.datasource.url=$SPRING_DATASOURCE_URL -Dspring.liquibase.url=$SPRING_LIQUIBASE_URL -Dspring.datasource.username=$SPRING_DATASOURCE_USERNAME -Dspring.datasource.password=$SPRING_DATASOURCE_PASSWORD -jar baby-0.0.1-SNAPSHOT.jar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
https://github.com/renanfranca/mamazinha-monolithic/blob/publish-to-flydotio/Dockerfile





&lt;p&gt;To build the final jar and optimize the baby application for production, run:&lt;br&gt;
&lt;code&gt;./mvnw -Pprod clean verify&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then I have to create a docker image locally from Dockerfile using this command at the project root folder &lt;code&gt;docker build -t stting/mamazinhaflyio .&lt;/code&gt;. Replace &lt;code&gt;stting&lt;/code&gt; with your &lt;a href="https://hub.docker.com/"&gt;dockerhub account&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The last step is to open the docker desktop and push the created image to the docker hub.&lt;/p&gt;
&lt;h3&gt;
  
  
  Create flyio dockerfile
&lt;/h3&gt;

&lt;p&gt;I created the flyio folder &lt;code&gt;flyio&lt;/code&gt; in the root directory of my project. Inside that folder I created another dockerfile to push to flyio, doing this way you won't use the fly.io image builder, only pull from the docker hub (this makes the deployment much faster):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; stting/mamazinhaflyio:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
https://github.com/renanfranca/mamazinha-monolithic/blob/publish-to-flydotio/flyio/Dockerfile





&lt;h3&gt;
  
  
  Create the flyio application
&lt;/h3&gt;

&lt;p&gt;Let's go to the folder &lt;code&gt;flyio&lt;/code&gt; and run the command &lt;code&gt;flyctl launch&lt;/code&gt; and I choose the following options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating app in C:\Users\Blog\Documents\Projects\mamazinha-monolithic\flyio&lt;/li&gt;
&lt;li&gt;Scanning source code&lt;/li&gt;
&lt;li&gt;Detected a Dockerfile app&lt;/li&gt;
&lt;li&gt;? App Name (leave blank to use an auto-generated name): mamazinha-app&lt;/li&gt;
&lt;li&gt;? App Name (leave blank to use an auto-generated name): mamazinha-app&lt;/li&gt;
&lt;li&gt;Automatically selected personal organization: Renan Franca&lt;/li&gt;
&lt;li&gt;? Select region: gru (São Paulo)&lt;/li&gt;
&lt;li&gt;Created app mamazinha-app in organization personal&lt;/li&gt;
&lt;li&gt;Wrote config file fly.toml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After running that command you will have an already configured &lt;code&gt;fly.toml&lt;/code&gt; file with your application info and everything you need to deploy it 🤩.&lt;/p&gt;

&lt;h4&gt;
  
  
  Define the environment variables
&lt;/h4&gt;

&lt;p&gt;You have to open the &lt;code&gt;fly.toml&lt;/code&gt; file and edit the [env] section with the variables (replace the values with your recently created postgres app):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;  _JAVA_OPTIONS="-XX:MaxRAM=70m"
  SPRING_PROFILES_ACTIVE="prod,api-docs"
  MANAGEMENT_METRICS_EXPORT_PROMETHEUS_ENABLED="false"
  SPRING_DATASOURCE_USERNAME="postgres"
  SPRING_DATASOURCE_URL="jdbc:postgresql://app-postgres-name.internal:5432/databasename"
  SPRING_LIQUIBASE_URL="jdbc:postgresql://app-postgres-name.internal:5432/databasename"
  JHIPSTER_SLEEP=5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
https://github.com/renanfranca/mamazinha-monolithic/blob/publish-to-flydotio/flyio/fly.toml





&lt;p&gt;&lt;strong&gt;WARNING&lt;/strong&gt;: about the postgres database URL for java. The &lt;a href="https://fly.io/docs/reference/postgres/"&gt;postgres start guide&lt;/a&gt; examples didn't consider java language and the URL to connect to postgres which they gave to me after creating the postgres instance was that: &lt;code&gt;postgres://baby-postgres.internal:5432/baby&lt;/code&gt;. To solve the problem I change the prefix postgres to postgresql: &lt;code&gt;jdbc:postgresql://baby-postgres.internal:5432/baby&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Define the database password
&lt;/h4&gt;

&lt;p&gt;You can use the secret option to keep your database password safe! Run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flyctl secrets set DB_POSTGRES_PASSWORD=pasteHereThePassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will create an encrypted environment variable. To list your secrets, run the command &lt;code&gt;flyctl secrets list&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy the application
&lt;/h3&gt;

&lt;p&gt;Run the command &lt;code&gt;flyctl deploy&lt;/code&gt; . To open your already deployed application in a browser, run the command &lt;code&gt;flyctl open&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read this jhipster user
&lt;/h2&gt;

&lt;p&gt;Before deploying the app, you can test it using the docker desktop.&lt;/p&gt;

&lt;p&gt;First, edit the file &lt;code&gt;src/main/docker/app.yml&lt;/code&gt; to use the docker image &lt;code&gt;stting/mamazinhaflyio&lt;/code&gt; (in my case):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# This configuration is intended for development purpose, it's **your** responsibility to harden it for production &lt;/span&gt;
 version: '3.8' 
 services: 
   baby-app: 
     image: stting/mamazinhaflyio 
     environment: 
       - _JAVA_OPTIONS=-Xmx128m -Xms128m 
       - SPRING_PROFILES_ACTIVE=prod,api-docs 
       - MANAGEMENT_METRICS_EXPORT_PROMETHEUS_ENABLED=false 
       - SPRING_DATASOURCE_URL=jdbc:postgresql://baby-postgresql:5432/baby 
       - SPRING_LIQUIBASE_URL=jdbc:postgresql://baby-postgresql:5432/baby 
       - JHIPSTER_SLEEP=30 # gives time for other services to boot before the application 
       - SPRING_DATASOURCE_USERNAME=baby 
       - SPRING_DATASOURCE_PASSWORD= 
     # If you want to expose these ports outside your dev PC, 
     # remove the "127.0.0.1:" prefix 
     ports: 
       - 127.0.0.1:8080:8080 
     deploy: 
       resources: 
         limits: 
           memory: 256M 
   baby-postgresql: 
     image: postgres:14.2 
     # volumes: 
     #   - ~/volumes/jhipster/baby/postgresql/:/var/lib/postgresql/data/ 
     environment: 
       - POSTGRES_USER=baby 
       - POSTGRES_PASSWORD= 
       - POSTGRES_HOST_AUTH_METHOD=trust 
     # If you want to expose these ports outside your dev PC, 
     # remove the "127.0.0.1:" prefix 
     ports: 
       - 5432:5432
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
https://github.com/renanfranca/mamazinha-monolithic/blob/publish-to-flydotio/src/main/docker/app.yml





&lt;p&gt;Then run the command &lt;code&gt;docker-compose -f src/main/docker/app.yml up -d&lt;/code&gt; and access your application at &lt;code&gt;http://localhost:8080&lt;/code&gt; which is using postgres database.&lt;/p&gt;

&lt;h2&gt;
  
  
  My own experience with fly.io
&lt;/h2&gt;

&lt;p&gt;I am running my Baby Care App on fly.io since 03 September 2022, here is the link: &lt;a href="https://renanfranca.github.io/redirect/babycareapp.html"&gt;Mamazinha Baby Care App&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I accessed the app every day at least 10 times a day, I only got 5 downtimes the first week. After that, my wife and I didn't notice any downtime 😊! It looks like the app was always warmed up and ready to receive requests.&lt;/p&gt;

&lt;p&gt;On the dashboard web app, you can see a lot of information about your app: &lt;a href="https://fly.io/dashboard"&gt;https://fly.io/dashboard&lt;/a&gt;. My application constantly uses 226 MB from the 232 MB available. In addition, you can access the Grafana dashboard &lt;a href="https://fly-metrics.net/"&gt;https://fly-metrics.net/&lt;/a&gt; for awesome insight info 👏!&lt;/p&gt;

&lt;h2&gt;
  
  
  🌟Feedback
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If you like this project, please, considering give it a star 🌟 to support me and enhanced the repository's visibility 🤩!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/renanfranca/mamazinha-monolithic"&gt;•⭐mamazinha-monolithic&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💙 Special Thanks
&lt;/h2&gt;

&lt;p&gt;I just wanna say thanks to the fly.io team for adding this free high-quality free tier option! It has the bearing minimum for your MVP version and to use it to host your portfolio projects!&lt;/p&gt;

&lt;p&gt;Thank you &lt;a href="https://twitter.com/pascalgrimaud?t=aUYEiYODOpXITMcmTOkbOQ&amp;amp;s=09"&gt;@pascalgrimaud&lt;/a&gt; for being available to chat and help me out when I've got stuck! It's important to read another point of view when I can't move on.&lt;/p&gt;

&lt;p&gt;Last but not least, thank you JHipster Community!&lt;/p&gt;

</description>
      <category>jhipster</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>java</category>
    </item>
    <item>
      <title>JHipster does not use lombok. Why?</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Fri, 26 Aug 2022 06:22:00 +0000</pubDate>
      <link>https://dev.to/renanfranca/jhipster-does-not-use-lombok-why-12o9</link>
      <guid>https://dev.to/renanfranca/jhipster-does-not-use-lombok-why-12o9</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/jhipster-does-not-use-lombok-why.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After I run the &lt;a href="https://renanfranca.github.io/2022/03/08/my-reasons-to-use-jhipster.html"&gt;JHipster generator&lt;/a&gt;  for the first time I realized that the back end implemented with spring boot doesn't use &lt;a href="https://projectlombok.org/"&gt;Lombok&lt;/a&gt;. So I decided to customize the generated code to use lombok than I realized it wasn't the best way to use JHipster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customize JHipster
&lt;/h2&gt;

&lt;p&gt;When &lt;a href="https://renanfranca.github.io/2022/02/24/why-did-i-use-jhipster.html"&gt;I realized how awesome JHipster was&lt;/a&gt; I thought that I should change the generated code to be like the one I used to type manually. So I saw the opportunity to create my own &lt;a href="https://www.jhipster.tech/modules/creating-a-blueprint/"&gt;blueprint&lt;/a&gt; with the following custom annotations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add Lombok - @lombok&lt;/li&gt;
&lt;li&gt;Hide comment - @noCodeComment&lt;/li&gt;
&lt;li&gt;Change the database scheme - @schema&lt;/li&gt;
&lt;li&gt;Add &lt;a href="https://www.baeldung.com/jpa-get-auto-generated-id"&gt;Id GeneratedValue&lt;/a&gt; to entity - @generatedValue(identity)&lt;/li&gt;
&lt;li&gt;Define column database name - @column(ds_field) &lt;/li&gt;
&lt;li&gt;Use unsupported types - @newFieldTypeImport(import_class_package_type) and @newFieldType(type)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I opened source my blueprint which customize the server side code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/renanfranca/generator-jhipster-custom-server-side-blueprint-private/tree/custom-annotations-options"&gt;generator-jhipster-custom-server-side-blueprint-private&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Here is the class which implement those custom annotations options: &lt;a href="https://github.com/renanfranca/generator-jhipster-custom-server-side-blueprint-private/blob/custom-annotations-options/generators/entity/index.js#L170"&gt;https://github.com/renanfranca/generator-jhipster-custom-server-side-blueprint-private/blob/custom-annotations-options/generators/entity/index.js&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a jdl file example which uses my blueprint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@lombok&lt;/span&gt;  
&lt;span class="nd"&gt;@schema&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyProject&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
&lt;span class="nd"&gt;@noCodeComment&lt;/span&gt; 
&lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="nf"&gt;RenanClasse&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RenanOk&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;  
&lt;span class="nd"&gt;@generatedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;identity&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;  
&lt;span class="nd"&gt;@column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ds_name&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="nd"&gt;@newFieldTypeImport&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;java_time_LocalDateTime&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
&lt;span class="nd"&gt;@newFieldType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LocalDateTime&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  
&lt;span class="n"&gt;birthday&lt;/span&gt; &lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;  

&lt;span class="c1"&gt;// Use Data Transfer Objects (DTO)  &lt;/span&gt;
&lt;span class="n"&gt;dto&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;mapstruct&lt;/span&gt;  

&lt;span class="c1"&gt;// Service layer  &lt;/span&gt;
&lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;serviceClass&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  JHipster choose not use Lombok
&lt;/h2&gt;

&lt;p&gt;I found an &lt;a href="https://github.com/jhipster/generator-jhipster/issues/398"&gt;issue at jhipster generated project&lt;/a&gt; that list the the reasons to not use lombok. I will quote some of them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;blockquote&gt;
&lt;p&gt;On one project, a new version of the Lombok plugin caused the IDE to crash (I think this was Intellij). So nobody could work anymore.&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;blockquote&gt;
&lt;p&gt;On another project, Lombok made the CI server crash (and would have probably caused the production server to crash), as it triggered a bug in the JVM&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;blockquote&gt;
&lt;p&gt;On a third project, we achieved 30% performance increase by recoding the equals/hashcode from Lombok&lt;/p&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;li&gt;&lt;blockquote&gt;
&lt;p&gt;Then, for JHipster, the story is also that we can't ask people to install a plugin on their IDE:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;1st goal is to have a smooth experience: you generate the app and it works in your IDE, by default&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;2nd goal is that you can use whatever IDE you want. And some people have very exotic things, for example I just tried &lt;a href="https://codenvy.com/"&gt;https://codenvy.com/&lt;/a&gt; -&amp;gt; no plugin for this one, of course&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Entity implementation
&lt;/h3&gt;

&lt;p&gt;In the following example you can see that JHipster implements manually sets and gets. Beyond that you can see it's implement what is called fluent method as I learn it from the &lt;a href="https://github.com/jhipster/generator-jhipster/blob/46b7cf2f8358fa60eaafffdfe242b2873af86ea9/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs#L487"&gt;JHipster generator source code&lt;/a&gt; and from &lt;a href="https://github.com/jhipster/generator-jhipster/pull/3751"&gt;this issue &lt;/a&gt;which discuss fluent setters implementation at jhipster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"nap"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Cache&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CacheConcurrencyStrategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;READ_WRITE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;serialVersionUID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1L&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SEQUENCE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"sequenceGenerator"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@SequenceGenerator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"sequenceGenerator"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"start"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"jhi_end"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Enumerated&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;EnumType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;STRING&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"place"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Place&lt;/span&gt; &lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@ManyToOne&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;BabyProfile&lt;/span&gt; &lt;span class="n"&gt;babyProfile&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@ManyToOne&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Humor&lt;/span&gt; &lt;span class="n"&gt;humor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// jhipster-needle-entity-add-field - JHipster will add fields here&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt; &lt;span class="nf"&gt;getStart&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setStart&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setStart&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt; &lt;span class="nf"&gt;getEnd&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt; &lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setEnd&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Place&lt;/span&gt; &lt;span class="nf"&gt;getPlace&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;place&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt; &lt;span class="nf"&gt;place&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Place&lt;/span&gt; &lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setPlace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setPlace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Place&lt;/span&gt; &lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;place&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;BabyProfile&lt;/span&gt; &lt;span class="nf"&gt;getBabyProfile&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;babyProfile&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setBabyProfile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BabyProfile&lt;/span&gt; &lt;span class="n"&gt;babyProfile&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;babyProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;babyProfile&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt; &lt;span class="nf"&gt;babyProfile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BabyProfile&lt;/span&gt; &lt;span class="n"&gt;babyProfile&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setBabyProfile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;babyProfile&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Humor&lt;/span&gt; &lt;span class="nf"&gt;getHumor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;humor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setHumor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Humor&lt;/span&gt; &lt;span class="n"&gt;humor&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;humor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;humor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt; &lt;span class="nf"&gt;humor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Humor&lt;/span&gt; &lt;span class="n"&gt;humor&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setHumor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;humor&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(((&lt;/span&gt;&lt;span class="nc"&gt;Nap&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// see https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getClass&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;hashCode&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// prettier-ignore&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Nap{"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"id="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;", start='"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;getStart&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"'"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;", end='"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;getEnd&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"'"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;", place='"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;getPlace&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"'"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
            &lt;span class="s"&gt;"}"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;source: &lt;a href="https://github.com/renanfranca/mamazinha-baby/blob/main/src/main/java/com/mamazinha/baby/domain/Nap.java"&gt;&lt;em&gt;Nap.java&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you can create this object like when you use the builder pattern but it's not immutable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Nap&lt;/span&gt; &lt;span class="n"&gt;nap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Nap&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;plusHours&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I enjoyed this implementation and that's enough for me to keep my code less verbose.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is the way
&lt;/h2&gt;

&lt;p&gt;I gave up to customize JHipster generated code.&lt;br&gt;
I realized that I should accept the jhipster generated code pattern because If I try to customize everything I am creating my own JHipster and I am going to lose the productivity which JHipster could bring to my workflow.&lt;br&gt;
It isn't a trivial job to maintain a blueprint up to date with the latest jhipster generator version. So I advise you to only create a blueprint if it is extremely necessary.&lt;/p&gt;

</description>
      <category>jhipster</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>java</category>
    </item>
    <item>
      <title>Publishing Microservices into Google Kubernetes Engine (GKE)</title>
      <dc:creator>Renan Franca</dc:creator>
      <pubDate>Mon, 11 Jul 2022 10:34:56 +0000</pubDate>
      <link>https://dev.to/renanfranca/publishing-microservices-into-google-kubernetes-engine-gke-3hh3</link>
      <guid>https://dev.to/renanfranca/publishing-microservices-into-google-kubernetes-engine-gke-3hh3</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://renanfranca.github.io/publishing-microservices-into-gke.html?utm_source=dev.to&amp;amp;utm_medium=social&amp;amp;utm_campaign=promote-blog"&gt;renanfranca.github.io&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I will show you how to publish the &lt;a href="https://renanfranca.github.io/i-built-a-baby-care-web-app-using-jhipster.html" rel="noopener noreferrer"&gt;Mamazinha Baby Care Web App - Open Source Project&lt;/a&gt; on &lt;a href="https://cloud.google.com/kubernetes-engine" rel="noopener noreferrer"&gt;Google Kubernetes Engine (GKE)&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Before we start
&lt;/h2&gt;

&lt;p&gt;I used JHipster to build the web app, everything you need to know about how to generate the Kubernetes (k8s) yml files to publish on GKE is detailed step by step &lt;a href="https://developer.okta.com/blog/2021/06/01/kubernetes-spring-boot-jhipster" rel="noopener noreferrer"&gt;in this tutorial (I strongly recommend watching the video first before getting your hand dirty 😁)&lt;/a&gt;  created by &lt;a href="https://twitter.com/mraible" rel="noopener noreferrer"&gt;@mraible&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing on GKE
&lt;/h2&gt;

&lt;p&gt;I open source the yaml files that i used to publish on GKE:&lt;br&gt;
 &lt;a href="https://github.com/renanfranca/mamazinha-k8s/tree/google-cloud" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fmamazinha-baby-care%2Fgithub-mamazinha-k8s-image_readme.png" alt="renanfranca/mamazinha-k8s"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ll cover here the Google Cloud configuration that I made to run my project as cheap as possible. My goal is to keep the cost below or near the &lt;a href="https://cloud.google.com/free/" rel="noopener noreferrer"&gt;Always Free&lt;/a&gt; tiers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The GKE free tier provides $74.40 in monthly credits per billing account that are applied to zonal and Autopilot clusters. If you only use a single Zonal or Autopilot cluster, this credit will at least cover the complete cost of that cluster each month. Unused free tier credits are not rolled over, and cannot be applied to any other SKUs (for example, they cannot be applied to compute charges, or the cluster fee for Regional clusters).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Initial setup
&lt;/h3&gt;

&lt;p&gt;So I made this pricing simulation (I choose São Paulo as my Region because I am from Brazil):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fprice-simulation.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fprice-simulation.png" alt="Pricing simulation"&gt;&lt;/a&gt;&lt;/p&gt;

https://cloud.google.com/products/calculator/#id=d2a4523b-27f9-4a35-950b-924cd8b0d590



&lt;p&gt;After logging in at Google Cloud Console, Let’s create the Cluster Zone and the first Node Pool&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fopen-gke-standar-option.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fopen-gke-standar-option.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Open GKE Standar Option



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fcluster-options.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fcluster-options.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Choose those options. Only edit the cluster name and the cluster zone (choose the nearest zone from your location or your client location)



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fcluster-created-screen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fcluster-created-screen.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
You will end up with something like this



&lt;p&gt;Now you have to connect to your cluster. Install google cloud SDK and install Google kubectl (I'm using windows)&lt;br&gt;
&lt;code&gt;gcloud components install kubectl&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;On git bash:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;confirm that the installation was successful &lt;code&gt;wich kubectl&lt;/code&gt; and the response should be something like
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/c/Users/AccountName/AppData/Local/Google/Cloud SDK/google-cloud-sdk/bin/kubectl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;execute the following command to connect to your cluster, change &lt;code&gt;mamazinha&lt;/code&gt; to your cluster name and change &lt;code&gt;southamerica-east1-a&lt;/code&gt; to your zone
&lt;code&gt;gcloud container clusters get-credentials mamazinha -zone=southamerica-east1-a&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can now publish the yml files to GKE:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;clone the repository &lt;code&gt;git clone git@github.com:renanfranca/mamazinha-k8s.git&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Switch to google-cloud branch &lt;code&gt;git checkout google-cloud&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;On git bash go to the root of the cloned project folder and run the command &lt;code&gt;./kubectl-apply.sh -f&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Install the amazing k9s &lt;a href="https://k9scli.io/topics/install/" rel="noopener noreferrer"&gt;https://k9scli.io/topics/install/&lt;/a&gt; and type the command to connect to your cluster &lt;code&gt;k9s -n mamazinha&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fk9s-home-screen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fk9s-home-screen.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
k9s home screen



&lt;p&gt;As you can see only 3 nodes weren't enough for my project, after digging around I discovered &lt;a href="https://cloud.google.com/kubernetes-engine/docs/how-to/preemptible-vms?_ga=2.47436577.-747971199.1636929609" rel="noopener noreferrer"&gt;the preemptible VM option&lt;/a&gt; 😆! The registry/baby microservice both are stateless, so I don't care if after 24h the VM will be destroyed and they will be initialized at another VM.&lt;/p&gt;

&lt;p&gt;Let’s create a new node pool with a preemptible VM which costs less than the regular machine type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fadd-node-pool-menu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fadd-node-pool-menu.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Go to Cluster Kubernetes Engine &amp;gt; Clusters &amp;gt; Clique on your cluster &amp;gt; clique on ADD NODE POOL



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fnode-pool-details.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fnode-pool-details.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Only one node number



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fnode-pool-detail-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fnode-pool-detail-2.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
You must mark the node as preemptible! Then click on CREATE! 🤩



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fcreated-preemptible-node.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fcreated-preemptible-node.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Now we can see 4 nodes and only one preemptible



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fk9s-node-24h-shutdown.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fk9s-node-24h-shutdown.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
That’s what happened after 24h! Shutdown the preemptible VM 😜



&lt;p&gt;The cluster is ready! But how to choose the place to deploy each component of my project? The Postgres database can’t be deployed at the preemptible node, because the data will be lost every 24hrs!&lt;/p&gt;

&lt;p&gt;The answer is &lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity" rel="noopener noreferrer"&gt;NodeAffinity&lt;/a&gt;, let’s take the gateway as an example. I want to always deploy the gateway on the node &lt;code&gt;gke-mamazinha-pool-small-cost-03fa0890-zqn0&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Create a label for the node &lt;code&gt;kubectl label nodes gke-mamazinha-pool-small-cost-03fa0890-zqn0 app=gateway&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Add this nodeAffinity property to my yml file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2FnodeAffinity-property.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2FnodeAffinity-property.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
gateway-deployment.yml



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Change to&lt;code&gt;replicas: 0&lt;/code&gt; and apply the deployment yml to terminate every gateway running instances &lt;code&gt;kubectl apply -f gateway-k8s/gateway-deployment.yml -n mamazinha&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change back to &lt;code&gt;replicas: 1&lt;/code&gt; and apply again &lt;code&gt;kubectl apply -f gateway-k8s/gateway-deployment.yml -n mamazinha&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repeat this for the other components if you want to deploy at a specific node.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the real cost of this configuration. I am from Brazil, so the costs are in my country's currency. You can do the conversion by knowing that $1 Dollar was R$5,40 Reais when I capture the print screen from the following billing report.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fstandard-node-cost.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fstandard-node-cost.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Mamazinha Google Cloud Project billing report



&lt;h3&gt;
  
  
  Final setup
&lt;/h3&gt;

&lt;p&gt;The preemptible VM cost 80% less than the regular machine, so my goal was to use only preemptible. The only way I figured it out to do this is to create &lt;a href="https://cloud.google.com/architecture/deploying-highly-available-postgresql-with-gke#deploy_postgresql_to_the_regional_gke_cluster" rel="noopener noreferrer"&gt;persistent volume on my kubernetes cluster&lt;/a&gt; for each Postgres database because after 24h even the Postgres could be shut down without losing data.&lt;/p&gt;

&lt;p&gt;First I &lt;a href="https://cloud.google.com/architecture/deploying-highly-available-postgresql-with-gke#set_up_port_forwarding" rel="noopener noreferrer"&gt;port-forward the Postgres pods&lt;/a&gt; to backup the data using &lt;a href="https://www.pgadmin.org/download/" rel="noopener noreferrer"&gt;pgAdmin&lt;/a&gt; then I defined the persistence volume in the yml file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fpersistence-volume-property.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fpersistence-volume-property.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
gateway-postgresql.yml (partial)



&lt;p&gt;The next step was to delete the regular machine-type node pool then I resize the preemptible node pool to have 4 nodes.&lt;/p&gt;

&lt;p&gt;After that, I apply both yml files ( &lt;code&gt;kubectl apply -f baby-k8s/baby-postgresql.yml -n mamazinha&lt;/code&gt; and &lt;code&gt;kubectl apply -f gateway-k8s/gateway-postgresql.yml -n mamazinha&lt;/code&gt;) and restore the backup using pgAdmin that will be stored at the persistent volume.&lt;/p&gt;

&lt;p&gt;With this approach, my web app is going to have downtime every 24hrs. To mitigate that I decided to deploy everything simultaneously so after 24h everything will be shut down and going up in 2 minutes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fk9s-pods-same-time.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fk9s-pods-same-time.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
All pods running on preemptible nodes at the same time



&lt;h3&gt;
  
  
  The final cost
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://cloud.google.com/kubernetes-engine/pricing#:~:text=The%20cluster%20management%20fee%20of,to%20zonal%20and%20Autopilot%20clusters." rel="noopener noreferrer"&gt;According to Google Pricing&lt;/a&gt;, the cluster manager fee will be free.&lt;/p&gt;

&lt;p&gt;After using only preemptible nodes the cost was reduced a lot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fpreemptible-billing-report.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fpreemptible-billing-report.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Mamazinha billing report after using only preemptible nodes



&lt;p&gt;The invoice from January 2022 was R$844,09 (~$162.14), I don’t think it is too expensive. But I can’t afford this value by myself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fjanuary-billing-report.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Fjanuary-billing-report.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
The cost from January 2022



&lt;p&gt;So I couldn't keep the web app online on Google Cloud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Funtil-shutdown-billing-report.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Frenanfranca.github.io%2Fimg%2Fpublishing-microservices-gke%2Funtil-shutdown-billing-report.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
The cost until I shut down the web app



&lt;h2&gt;
  
  
  How was my experience with Google Cloud?
&lt;/h2&gt;

&lt;p&gt;Google cloud platform is easy to use and I set things up quickly. I could learn while I was using it, I could undo, destroyed and build easily 😆&lt;/p&gt;

&lt;p&gt;I think Google Cloud should have a real free plan for small microservices applications, so the user will pay when the product gain traction and started to be used ☺&lt;/p&gt;

&lt;h3&gt;
  
  
  Now it's your turn! How was your experience with Google Cloud?
&lt;/h3&gt;

&lt;p&gt;I will enjoy to read your comments 🤗&lt;/p&gt;

&lt;p&gt;If you have any question feel free to ask me anything here or Direct Message (DM) me on Twitter  &lt;a href="https://www.twitter.com/renan_afranca" rel="noopener noreferrer"&gt;@renan_afranca&lt;/a&gt; (follow me and I will follow you back to unlock the DM option).&lt;/p&gt;

</description>
      <category>jhipster</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
