<?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>Forem: Wildan S. Nahar</title>
    <description>The latest articles on Forem by Wildan S. Nahar (@wildan3105).</description>
    <link>https://forem.com/wildan3105</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%2F11842%2F3b0d815b-b9cb-41af-96db-62738468f292.jpeg</url>
      <title>Forem: Wildan S. Nahar</title>
      <link>https://forem.com/wildan3105</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/wildan3105"/>
    <language>en</language>
    <item>
      <title>How I rebuild my hobby project in over 2 weekends with ChatGPT &amp; Claude</title>
      <dc:creator>Wildan S. Nahar</dc:creator>
      <pubDate>Sat, 28 Feb 2026 01:15:06 +0000</pubDate>
      <link>https://forem.com/wildan3105/how-i-rebuild-my-hobby-project-in-over-2-weekends-with-chatgpt-claude-3jmb</link>
      <guid>https://forem.com/wildan3105/how-i-rebuild-my-hobby-project-in-over-2-weekends-with-chatgpt-claude-3jmb</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;I rebuilt my hobby project in over 2 weeks with the help of OpenAI's ChatGPT and Antrophic's Claude (Sonnet 4.5). In this post, I am going to share the details on how I do it: the fun things, the trade-offs, and takeaways. &lt;/p&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;I started this project called &lt;code&gt;github-langs&lt;/code&gt; (site: &lt;a href="https://gitstats.wildans.us" rel="noopener noreferrer"&gt;https://gitstats.wildans.us&lt;/a&gt;) back in 2017. It was the very first time for me to get into so-called open-source project. I remember vividly that Hacktoberfest got me into it. &lt;/p&gt;

&lt;p&gt;For those who don't know, "Hacktoberfest" &lt;em&gt;was&lt;/em&gt; a month-long activity that held by DigitalOcean and GitHub (at least how it was in 2017) where developers around the world try to collaborate each other in the spirit of open-source project: everyone can be anything from maintainer to contributor and users. &lt;/p&gt;

&lt;p&gt;And I did become one of them. I created the &lt;strong&gt;github-langs&lt;/strong&gt; project, a web-based application to visualize the language distribution for a given github account. This is how it looked back then (and still is at &lt;a href="https://gitstats.wildans.site):" rel="noopener noreferrer"&gt;https://gitstats.wildans.site):&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fwildan3105%2Fwildans.site%2Frefs%2Fheads%2Fmain%2Fpublic%2Fimages%2Fprojects%2Fproject-1.png%3Ftoken%3DGHSAT0AAAAAADGSMTBRKPMGLJZ3RE64BDEE2NCGYBA" 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%2Fraw.githubusercontent.com%2Fwildan3105%2Fwildans.site%2Frefs%2Fheads%2Fmain%2Fpublic%2Fimages%2Fprojects%2Fproject-1.png%3Ftoken%3DGHSAT0AAAAAADGSMTBRKPMGLJZ3RE64BDEE2NCGYBA" alt="github-langs-screenshot" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Super simple. You enter a GitHub username and once it's found on GitHub database, it will visualize the language distribution (if an account does have repository with certain language, of course). Some of the features are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Toggle between colorful and white-only color&lt;/li&gt;
&lt;li&gt;Download the bar chart&lt;/li&gt;
&lt;li&gt;Share to X and Facebook&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that's it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Goals
&lt;/h2&gt;

&lt;p&gt;I have been meaning to rebuild this project from several years ago. But due to other commitments and stuffs, I haven't really gotten the time to do it. I have some ideas, both for the features as well as technical improvements, but it was just playing around over my head. Haven't really put it into concrete, actionable ideas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generative AI
&lt;/h3&gt;

&lt;p&gt;Since this become a thing, I can see that people with limited technical proficiency and knowledge can really build something out of nothing. Then I think; with my "enough" technical knowledge and proficiency, surely I can make that long, sleep ideas come into reality, can't I?&lt;/p&gt;

&lt;p&gt;So I give it a shot.&lt;/p&gt;

&lt;h3&gt;
  
  
  New look
&lt;/h3&gt;

&lt;p&gt;Here is what it looks like now (you can access this via &lt;a href="https://gitlingo.app" rel="noopener noreferrer"&gt;https://gitlingo.app&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Homepage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F7030099%2F556228285-5a650f93-66fe-4ed6-9a3b-a68a0b725edc.png%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyMzkxNTEsIm5iZiI6MTc3MjIzODg1MSwicGF0aCI6Ii83MDMwMDk5LzU1NjIyODI4NS01YTY1MGY5My02NmZlLTRlZDYtOWEzYi1hNjhhMGI3MjVlZGMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDIyOCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAyMjhUMDAzNDExWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OTYzYzgzOGU5NDc1N2UxN2EwNDdjYWZkYTg2ODdjNWU1MjZhMDAyZGNlODM1YmU1NDRjY2JlOTY4YTY0YzRhNCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.SbavLM7KC3X5OoGDE16O5G8a4Kn-hUROUvT5rIApMiA" 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%2Fprivate-user-images.githubusercontent.com%2F7030099%2F556228285-5a650f93-66fe-4ed6-9a3b-a68a0b725edc.png%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyMzkxNTEsIm5iZiI6MTc3MjIzODg1MSwicGF0aCI6Ii83MDMwMDk5LzU1NjIyODI4NS01YTY1MGY5My02NmZlLTRlZDYtOWEzYi1hNjhhMGI3MjVlZGMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDIyOCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAyMjhUMDAzNDExWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OTYzYzgzOGU5NDc1N2UxN2EwNDdjYWZkYTg2ODdjNWU1MjZhMDAyZGNlODM1YmU1NDRjY2JlOTY4YTY0YzRhNCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.SbavLM7KC3X5OoGDE16O5G8a4Kn-hUROUvT5rIApMiA" alt="homepage" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Account overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F7030099%2F556228456-9b911692-a9ff-420b-8791-6ee0476d1ae4.png%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyMzkxNTEsIm5iZiI6MTc3MjIzODg1MSwicGF0aCI6Ii83MDMwMDk5LzU1NjIyODQ1Ni05YjkxMTY5Mi1hOWZmLTQyMGItODc5MS02ZWUwNDc2ZDFhZTQucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDIyOCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAyMjhUMDAzNDExWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MWM0OWM5ODZiYTdiN2I1ZDkyMjFmYTViZGIyNzBmNjA1OTkyMDRhZjhjMzdhMzA4NTc2MzYwNzljMDkwNDYzNSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.jtrmogkdb7DZWxh7PJdbjwut6cfJ09emlp-JHZpsTTE" 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%2Fprivate-user-images.githubusercontent.com%2F7030099%2F556228456-9b911692-a9ff-420b-8791-6ee0476d1ae4.png%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyMzkxNTEsIm5iZiI6MTc3MjIzODg1MSwicGF0aCI6Ii83MDMwMDk5LzU1NjIyODQ1Ni05YjkxMTY5Mi1hOWZmLTQyMGItODc5MS02ZWUwNDc2ZDFhZTQucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDIyOCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAyMjhUMDAzNDExWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MWM0OWM5ODZiYTdiN2I1ZDkyMjFmYTViZGIyNzBmNjA1OTkyMDRhZjhjMzdhMzA4NTc2MzYwNzljMDkwNDYzNSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.jtrmogkdb7DZWxh7PJdbjwut6cfJ09emlp-JHZpsTTE" alt="account-overview" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search result - language distribution&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;As you can clearly see, there are major overhaul for the functionality and UI/UX. I could say this new version offers simple, intuitive, and "elegant" look. &lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Instruction
&lt;/h3&gt;

&lt;p&gt;First and the foremost, this isn't something that can be done with "one-shot" prompt like: "Hey Claude, I want a new version of this new app with &lt;em&gt;the details&lt;/em&gt;. Please build me for it."&lt;/p&gt;

&lt;p&gt;I was inspired with this project called "whenwords" (&lt;a href="https://github.com/dbreunig/whenwords" rel="noopener noreferrer"&gt;https://github.com/dbreunig/whenwords&lt;/a&gt;); basically a relative time formatting library that only defines specification and let the AI generate corresponding language-specific implementation. It was quite game-changing.&lt;/p&gt;

&lt;p&gt;So I thought I can try it. Not really by creating a spec and then generate multiple github-langs in many different language, but more of how to write a good spec as well as test scenarios so that the output and outcome works as I would expect. &lt;/p&gt;

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

&lt;h4&gt;
  
  
  Weekend 1
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;As a disclaimer, I already know the "what, why, and &lt;em&gt;somewhat&lt;/em&gt; how"   to do it so it's easier for me to define this into AI-readable software specification. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So in the first weekend, it was really all about putting my thinkings into well-defined specification. In the beginning, I mainly wrote 2 specs: backend and frontend. From high-level view, here's how they looked like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Overview&lt;/span&gt;
&lt;span class="c"&gt;# Architecture&lt;/span&gt;
&lt;span class="c"&gt;# Stacks&lt;/span&gt;
&lt;span class="c"&gt;## Detailed architecture&lt;/span&gt;
&lt;span class="c"&gt;## Flowchart&lt;/span&gt;
&lt;span class="c"&gt;# Functional requirement&lt;/span&gt;
&lt;span class="c"&gt;# Non-functional requirement&lt;/span&gt;
&lt;span class="c"&gt;# API contracts (only for backend)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when writing the specification, I was also constantly consulting with ChatGPT to get the best out of it. So essentially, ChatGPT is used as "technical spec consultant" while Claude is mainly for the "coder". &lt;/p&gt;

&lt;p&gt;And when working with Claude, here's the visualized workflow:&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%2Fprivate-user-images.githubusercontent.com%2F7030099%2F556232619-de924f94-8a85-49b6-ab09-51737568d788.png%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyNDA2NDEsIm5iZiI6MTc3MjI0MDM0MSwicGF0aCI6Ii83MDMwMDk5LzU1NjIzMjYxOS1kZTkyNGY5NC04YTg1LTQ5YjYtYWIwOS01MTczNzU2OGQ3ODgucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDIyOCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAyMjhUMDA1OTAxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ODNkNDUzZjQ2OTFhNDkyOWU4MzgxMTYyNjRiZmEyODUwMWE3NTFlY2Y4OWI4ZmI5OGY0ZDVlOGJlODU4OTdiYyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.IA8nSFItL5PMwjsiLKqjK82VghxzHgC8O4xgkTRpaXA" 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%2Fprivate-user-images.githubusercontent.com%2F7030099%2F556232619-de924f94-8a85-49b6-ab09-51737568d788.png%3Fjwt%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzIyNDA2NDEsIm5iZiI6MTc3MjI0MDM0MSwicGF0aCI6Ii83MDMwMDk5LzU1NjIzMjYxOS1kZTkyNGY5NC04YTg1LTQ5YjYtYWIwOS01MTczNzU2OGQ3ODgucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDIyOCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAyMjhUMDA1OTAxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ODNkNDUzZjQ2OTFhNDkyOWU4MzgxMTYyNjRiZmEyODUwMWE3NTFlY2Y4OWI4ZmI5OGY0ZDVlOGJlODU4OTdiYyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.IA8nSFItL5PMwjsiLKqjK82VghxzHgC8O4xgkTRpaXA" alt="claude-workflow" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So by the end of the week (2-day work), I get a pretty good foundation for the backend / APIs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Weekend 2
&lt;/h4&gt;

&lt;p&gt;The focus was to built an MVP for the frontend to iterate on. Using the same workflow as shared above, the work is more about "give a clear, well-defined feature to be implemented with certain success criteria and test scenario" and less about "build something out of nothing" (which was the goal of the first week). So mainly I just create a couple of task list with some details and check by myself if it's implemented the way I would have wanted it.&lt;/p&gt;

&lt;p&gt;Example of the &lt;code&gt;.md&lt;/code&gt; task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## What&lt;/span&gt;

Add a segmented control: &lt;span class="sb"&gt;`Top 10`&lt;/span&gt;, &lt;span class="sb"&gt;`Top 25`&lt;/span&gt;, &lt;span class="sb"&gt;`All`&lt;/span&gt;.

&lt;span class="gu"&gt;## Why&lt;/span&gt;

Prevents unreadable charts and makes the UI instantly feel professional.

&lt;span class="gu"&gt;## How&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Sort languages descending by count (this is already done by the backend)
&lt;span class="p"&gt;-&lt;/span&gt; If Top 10/25 selected: slice N and sum the rest into &lt;span class="sb"&gt;`{ name: "Other", count: sum}`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; You can get creative about the color for "Other"
&lt;span class="p"&gt;-&lt;/span&gt; Apply this to all charts
&lt;span class="p"&gt;-&lt;/span&gt; Ensure the &lt;span class="sb"&gt;`10`&lt;/span&gt; and &lt;span class="sb"&gt;`25`&lt;/span&gt; are configurable so we can easily change/extend in the future if we want other segment

&lt;span class="gu"&gt;## Success criteria&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Switching Top-N updates chart instantly
&lt;span class="p"&gt;-&lt;/span&gt; "Other" appears only when applicable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Overall, this is quite satisfying result. I got really a solid codebase with really production-grade checklist as well as comprehensive tests. In particular, since the backend and frontend are written in TypeScript, I can easily jump between those easily without much of cognitive load or context-switching if they would've been written in different language.&lt;/p&gt;

&lt;p&gt;If anyone is interested to take a look at the repo, please head over here: &lt;a href="https://github.com/wildan3105/GitLingo" rel="noopener noreferrer"&gt;https://github.com/wildan3105/GitLingo&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;There are many things I want to do. However, 2 areas I want to focus on: &lt;/p&gt;

&lt;h3&gt;
  
  
  Feature development
&lt;/h3&gt;

&lt;p&gt;GitLingo still in the early "product-market fit" so to say. I'd like to get users trying on and have a say on what's good, what can be improved, what should be removed, etc. &lt;/p&gt;

&lt;p&gt;But I also have some ideas around the features to add and things to improve so let's see how things evolve from here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow adjustment
&lt;/h3&gt;

&lt;p&gt;In terms of workflow, personally, I'd like to code again. Because I believe at the end of the day it's my project, I initiated it and maintain it so I need to know the ins and outs of it. &lt;/p&gt;

&lt;p&gt;On the other hand, I can't lie that AI can be super fast and with the right information, can build things the way I would have done it or even better than I could do. &lt;/p&gt;

&lt;p&gt;So, let's see!&lt;/p&gt;

</description>
      <category>generativeai</category>
      <category>opensource</category>
      <category>hobby</category>
    </item>
    <item>
      <title>How to Make an Effective &amp; Efficient Pull Request</title>
      <dc:creator>Wildan S. Nahar</dc:creator>
      <pubDate>Fri, 04 Sep 2020 12:16:27 +0000</pubDate>
      <link>https://forem.com/wildan3105/how-to-make-an-effective-efficient-pull-request-570c</link>
      <guid>https://forem.com/wildan3105/how-to-make-an-effective-efficient-pull-request-570c</guid>
      <description>&lt;p&gt;As a software engineer, our day to day job is to solve problems primarily by coding. Several years ago, we used to use FTP (File Transfer Protocol) to move our local code to the remote server. But that is highly non-practical, not secure, and hard to track the changes. So here comes the version control, a tool that is used to track the code changes (author, file, commit, and timestamp) and to ease the collaboration among software engineers. And the best way to introduce changes using version control is via Pull Request (PR). &lt;/p&gt;

&lt;p&gt;Pull request for me is a "discussion platform" where every software engineer can jump in to review the code changes and approve it. But oftentimes, we don't do it in the correct way thus lead to headaches both for the reviewer and pull requester. In this post, I will share my knowledge that I get from experiences when creating a pull request to several repositories within my company. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;Before we go into the details, I think it's a good practice to raise the fundamental question: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why do we need to create an effective and efficient pull request? &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's an interesting question. At first, I believe it's not necessary if we only have a pair of programmers and sit close each other. At this point, we can just ask our partner to review it directly in our local machine or even if we create a pull request, it doesn't need to follow any rules, because our partner must have known what we are doing all the time. &lt;/p&gt;

&lt;p&gt;But, what if someday we need to work with hundreds of programmers from different teams across countries and in different timezone? The standard of each team's repository must be different: the branching strategy, the unit tests, the coding guideline, and PR review process itself. So this is when an effective and efficient PR is useful.&lt;/p&gt;

&lt;p&gt;The effective and efficient PR consists of a set of basic rules that are meant to be generic, so hopefully, everyone can follow it. This PR approach has some characteristics which are has reasonable-sized, focused, and does not have side-effects. Those are needed to reduce the reviewing time, introduce no bug, and eventually to solve the actual problems. &lt;/p&gt;

&lt;h1&gt;
  
  
  General Idea
&lt;/h1&gt;

&lt;p&gt;The first thing to notice when creating a pull request is to focus on the goal. What is the goal of the PR? Is it for fixing bug? Is it to introduce new error code? And so on. Once we define the goal, we can make the solution that is implemented in the code (addition/deletion). And the code should reflects that solution. Nothing more. So how can we do that? Here are my tips.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) Focus to solve the problem&lt;/strong&gt;&lt;br&gt;
The PR should only do one thing and do it right. Let's say the goal of the PR is to introduce new error code and how to handle it. So the solution to that goal is registering new error code. In addition, unit test to prove the change is working properly and not breaking the current implementation.&lt;/p&gt;

&lt;p&gt;For example, here is the simple PR to delete unused deployment files.&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%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-goal.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-goal.PNG" alt="The solution to the goal is clear: clean up unused files." width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In contrast, in this screenshot below shows how the goal is not clearly stated.&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%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-goal-bad-2.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-goal-bad-2.PNG" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) Code changes should reflect the solution&lt;/strong&gt;&lt;br&gt;
Sometimes we are too excited to create a PR that does a lot of things. This is totally not a good practice. For instance, in the big feature PR, we also fix typo or translation or formatting. Instead of creating PR that does a lot of things, we can create another small and quick-to-review PR for that specific goal. So the changes are still aligned with the main goal. &lt;/p&gt;

&lt;p&gt;An example of clean and straightforward PR.&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%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-changes-2.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-changes-2.PNG" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, this PR is doing unnecessary changes: extra line.&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%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-changes-bad.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-changes-bad.PNG" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This type of unnecessary changes can actually be prevented by having a git pre-commit hook. In that hook, we can do formatting such as running a linter tool to standardize the code format (no-console statement, space, comma-dangle, and so on). &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) Create a pull request template&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  DISCLAIMER
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;PR template is only available for GitHub (as long as I know), not sure about the other platforms such as GitLab or Bitbucket.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A template could be very useful. With the little effort to create a template (typically with the name PULL_REQUEST_TEMPLATE.md in the root folder in GitHub), it can hugely improve our pull request review process. We can define the goal of the changes, the type of changes, and also the checklist which is a list of the repository's code policy. You can see the example of my team's pull request template below. &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%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-template-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fpr-template-1.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At a glance, as a reviewer, we can see the summary of the PR by just looking or screening at the PR description. Even better, a repository that has a built-in PR template provides a consistent and well-structured PR description so if the repository has so many incoming PRs, it won't be a problem for reviewers since there's already a standard for creating a PR description. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4) Follow the proper commit convention&lt;/strong&gt;&lt;br&gt;
Git commit acts as a short description that reflects the changes we've made to the file(s). Essentially, it should only have one goal and or context (and in my opinion should be stateless). There are many commit conventions out there, but the ones that I trust so far are angular and commitizen. The proper commit message will help the reviewers when they try to search something specific in the PR and want to fully understand what is the requester trying to achieve. But still, the file changes are the source of truth for the review process. Best practice from me is to avoid using a single word for each commit message. Use full sentence instead so the reader won't be confused.&lt;/p&gt;

&lt;p&gt;Good, easy-to-read commit messages.&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%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fgood-commits.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fgood-commits.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unclear, incomplete commit messages.&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%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fbad-commits.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.wildan.us%2Fcontent%2Fimages%2F2020%2F08%2Fbad-commits.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This post is meant to cover the basic understanding on how to create an effective and efficient pull request. It doesn't explain much details as it aims to give the reader the brief principal to create an elegant PR so that the review process can run smoothly and focus on the substantial and significant things. Happy coding!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
