<?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: Gouranga Das Samrat</title>
    <description>The latest articles on DEV Community by Gouranga Das Samrat (@gouranga-das-khulna).</description>
    <link>https://dev.to/gouranga-das-khulna</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%2F2193879%2F834a1499-2027-4355-87be-bb678e90ae5c.jpg</url>
      <title>DEV Community: Gouranga Das Samrat</title>
      <link>https://dev.to/gouranga-das-khulna</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gouranga-das-khulna"/>
    <language>en</language>
    <item>
      <title>The PACELC Theorem — in a few words</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 17 May 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/the-pacelc-theorem-in-a-few-words-15f5</link>
      <guid>https://dev.to/gouranga-das-khulna/the-pacelc-theorem-in-a-few-words-15f5</guid>
      <description>&lt;p&gt;The PACELC theorem (often pronounced as &lt;code&gt;pack-else&lt;/code&gt;) was proposed by &lt;a href="https://dbmsmusings.blogspot.com/2010/04/problems-with-cap-and-yahoos-little.html" rel="noopener noreferrer"&gt;Daniel Abadi in 2010&lt;/a&gt; as an extension to the CAP theorem. While the CAP theorem focuses only on the behavior of a distributed system during a network partition, the PACELC theorem also pays lots of attention to a different state of a system - a state without any network partitions.&lt;/p&gt;

&lt;p&gt;Similarly as we did with the CAP theorem, we won’t just quote it and call it a day, instead, we will try to devise it ourselves from the ground up.&lt;/p&gt;

&lt;p&gt;But first, we should agree on the terminology! Two terms will be important for us today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Latency&lt;/strong&gt; — the PACELC theorem operates with the Latency as a (client-observed) duration of a write operation. The longer a client would have to wait until a write operation he has initiated completed — the higher the latency would be. This is not only the duration of the write operation on a single node, but the overall duration of the write operation as observed by the client. For clarity, the network round-trip time between the client and the system is not included in the latency.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Consistency&lt;/strong&gt; — while the CAP theorem operates only with the strong consistency (linearizability), for the PACELC theorem the consistency is a spectrum: it might vary from the strong consistency to the eventual consistency. For today’s discussion, we will consider the consistency as the degree to which all nodes in the system have the same data after a write operation completes, ranging from 1 (only entry node has written the new data) to N (all nodes have written the new data).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up the stage
&lt;/h2&gt;

&lt;p&gt;We are going to use a simple key-value store as a model for our thought experiment. This distributed system would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  be able to execute only one operation — &lt;code&gt;write&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;  consist of N nodes (obviously, at least two nodes — otherwise it won’t be a distributed system);&lt;/li&gt;
&lt;li&gt;  accept and execute &lt;code&gt;write&lt;/code&gt; operation requests on each node;&lt;/li&gt;
&lt;li&gt;  store the whole data set on each node (i.e., replicate all writes to all nodes).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The overall design of this toy key-value store would look like this:&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%2Fncn4ia1t4bpnc4s51rno.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%2Fncn4ia1t4bpnc4s51rno.png" alt="captionless image" width="621" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For illustration, here’s a simple API definition for such a system:&lt;/p&gt;

&lt;p&gt;We won’t focus on data read operations today, but we will assume that the system is able to read data as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maximizing consistency
&lt;/h2&gt;

&lt;p&gt;At first, we will try to ensure the strong consistency for our system. This means that a write operation should be considered completed only when all nodes have acknowledged it. Therefore, the write operation could only complete when the data change has been replicated to all nodes.&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%2Fpzf5ugfqjneldjq0kjfj.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%2Fpzf5ugfqjneldjq0kjfj.png" alt="captionless image" width="660" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This design would ensure that data consistency is maximized — once a write operation is completed, all nodes would have the same data. However, this comes at a cost of increased latency — the write operation would have to wait for the slowest node to acknowledge it. In a real-world scenario, this could be further exacerbated by network delays, node failures, or other issues that could slow down the replication process.&lt;/p&gt;

&lt;p&gt;Still, this design would provide the strongest consistency guarantees possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimizing latency
&lt;/h2&gt;

&lt;p&gt;Next, we will try to minimize the latency of our system. To achieve this, we could modify our write operation to complete as soon as the data is written to the first (entry) node, without waiting for the replication to other nodes to complete. The replication process would occur asynchronously in the background.&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%2Fyqcl5j7igoz6tj5hk3dq.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%2Fyqcl5j7igoz6tj5hk3dq.png" alt="captionless image" width="660" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This design would significantly reduce the latency of write operations, as they would complete as soon as the entry node acknowledges them. However, this comes at the cost of reduced consistency — there is a window of time during which not all nodes have the same data. If a read operation is performed during this window, it may return stale data from nodes that have not yet received the latest write.&lt;/p&gt;

&lt;p&gt;Even worse, a failure of the entry node before replication completes could lead to data loss, despite the write operation being acknowledged to the client!&lt;/p&gt;

&lt;h2&gt;
  
  
  The trade-off
&lt;/h2&gt;

&lt;p&gt;As we can see, there is a clear trade-off between maximizing consistency and minimizing latency in our distributed system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Maximizing consistency leads to higher latency, as write operations must wait for all nodes to acknowledge them.&lt;/li&gt;
&lt;li&gt;  Minimizing latency leads to reduced consistency, as write operations can complete before all nodes have the latest data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remembering the CAP theorem, we might think that this is a binary choice — either we have consistency or low latency. Let’s prove that this is not the case.&lt;/p&gt;

&lt;p&gt;We will alter the design of our system to allow for a configurable trade-off between consistency and latency. We can introduce a parameter &lt;code&gt;W&lt;/code&gt; (write quorum) that specifies the number of nodes that must acknowledge a write operation before it is considered complete. In this way, the value of &lt;code&gt;W&lt;/code&gt; would affect both the consistency and latency of the system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  With &lt;code&gt;W=N&lt;/code&gt; we would have the strongest consistency - as we have seen before in the &lt;a href="https://kapitanov.github.io/blog/posts/pacelc-theorem/#maximizing-consistency" rel="noopener noreferrer"&gt;"Maximizing consistency"&lt;/a&gt; chapter.&lt;/li&gt;
&lt;li&gt;  With &lt;code&gt;W=0&lt;/code&gt; we would have the lowest latency - as we have seen before in the &lt;a href="https://kapitanov.github.io/blog/posts/pacelc-theorem/#minimizing-latency" rel="noopener noreferrer"&gt;"Minimizing latency"&lt;/a&gt; chapter.&lt;/li&gt;
&lt;li&gt;  With &lt;code&gt;0 &amp;lt; W &amp;lt; N&lt;/code&gt; we would have a balance between consistency and latency - the higher the value of &lt;code&gt;W&lt;/code&gt;, the stronger the consistency and the higher the latency, and vice versa.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s illustrate one example — with &lt;code&gt;W=N/2 + 1&lt;/code&gt; (majority quorum):&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%2Fd6gipgeit5fi4lnd4tbe.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%2Fd6gipgeit5fi4lnd4tbe.png" alt="captionless image" width="660" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This design would provide a middle ground between consistency and latency. While the strong consistency is lost, the system would still provide a reasonable level of consistency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The majority of nodes would have the latest data after a write operation completes.&lt;/li&gt;
&lt;li&gt;  The latency would be defined by the latency of the slowest node in the majority, which is typically lower than waiting for all nodes. That said, the latency would still be higher than waiting for just one node, but it would be affected in a lesser degree by the latency spikes on a single node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good example of such a system is MongoDB, which allows clients to configure the write concern for write operations, including options for majority quorum — via so called &lt;strong&gt;write concern&lt;/strong&gt; option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally, the PACELC theorem
&lt;/h2&gt;

&lt;p&gt;While we can clearly see the connection between our thought experiment and the CAP theorem, there are some important differences to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The CAP theorem focuses on the trade-offs during network partitions. We put our focus on the other case — when there is no network partition.&lt;/li&gt;
&lt;li&gt;  The CAP theorem presents a binary choice between consistency and availability during partitions. We demonstrated a spectrum of trade-offs between consistency and latency in the absence of partitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this leads us to the PACELC theorem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In the presence of a network partition, a distributed system must choose between strong consistency and availability.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Else, when there is no network partition, a distributed system must choose between latency and the degree of consistency.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s easy to remember and decode the name of the theorem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;PAC&lt;/code&gt; means: "if &lt;strong&gt;P&lt;/strong&gt;artition happens, choose between &lt;strong&gt;A&lt;/strong&gt;vailability and &lt;strong&gt;C&lt;/strong&gt;onsistency" - the CAP theorem.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;ELC&lt;/code&gt; means: "&lt;strong&gt;E&lt;/strong&gt;lse, choose between &lt;strong&gt;L&lt;/strong&gt;atency and &lt;strong&gt;C&lt;/strong&gt;onsistency".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, it’s a great theorem — its whole meaning is encoded in its name!&lt;/p&gt;

&lt;p&gt;I would like to note one point, important for completeness.&lt;/p&gt;

&lt;p&gt;In the CAP theorem, we speak about strong consistency (linearizability) only. However, in the PACELC theorem, the consistency is a spectrum — from strong consistency to eventual consistency. And eventual consistency is non-binary — there are different degrees of eventual consistency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Ensuring that N-1 nodes might serve the stale data for some time is a weaker form of eventual consistency.&lt;/li&gt;
&lt;li&gt;  Ensuring that only the minority of nodes might serve the stale data for some time is a stronger form of eventual consistency.&lt;/li&gt;
&lt;li&gt;  Ensuring that not a single node might serve the stale data for some time is a strong consistency, not an eventual one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a caveat worth mentioning!&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>VS Code on Your Phone — Yes, It Actually Works 🔥</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Mon, 11 May 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/vs-code-on-your-phone-yes-it-actually-works-2obf</link>
      <guid>https://dev.to/gouranga-das-khulna/vs-code-on-your-phone-yes-it-actually-works-2obf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Extensions, IntelliSense, debuggers — the full experience, running natively on Android.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You've got VS Code running in Termux. You open it, install a Rust or Lua extension, and... the language server does nothing. No autocomplete. No error highlighting. Just silence.&lt;/p&gt;

&lt;p&gt;This happens to almost everyone. And the fix is simpler than you think.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;New here?&lt;/strong&gt; This guide assumes you already have Code-OSS (&lt;code&gt;code-oss&lt;/code&gt;) installed in Termux. If you haven't set that up yet, check out the previous post first — &lt;strong&gt;&lt;a href="https://dev.to/gouranga-das-khulna/turn-your-android-into-a-full-desktop-no-root-needed-4fl6"&gt;Turn Your Android Into a Full Desktop — No Root Needed&lt;/a&gt;&lt;/strong&gt; — which covers installing a full XFCE4 desktop with Code-OSS on Termux, no root, no hacks, no proot required. Come back here once you're set up. 👋&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This guide — based on the &lt;strong&gt;&lt;a href="https://github.com/GourangaDasSamrat/dotfiles" rel="noopener noreferrer"&gt;GourangaDasSamrat/dotfiles&lt;/a&gt;&lt;/strong&gt; repo — walks you through two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Making Code-OSS look and behave like the real Visual Studio Code (including access to the official VS Marketplace)&lt;/li&gt;
&lt;li&gt;Fixing language servers for &lt;strong&gt;Rust&lt;/strong&gt;, &lt;strong&gt;Lua&lt;/strong&gt;, and the &lt;strong&gt;CodeLLDB debugger&lt;/strong&gt; so they actually work on Termux&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🤔 Why Doesn't It Just Work Out of the Box?
&lt;/h2&gt;

&lt;p&gt;Termux ships &lt;code&gt;code-oss&lt;/code&gt; — the open-source build of VS Code. The problem is that VS Code extensions bundle their own pre-compiled binaries (language servers, debuggers), and those binaries are compiled for x86 Linux. They don't run on ARM Android.&lt;/p&gt;

&lt;p&gt;The fix? &lt;strong&gt;Install the correct ARM binaries via Termux's package manager, then symlink them&lt;/strong&gt; into the extension folders. Simple once you know it — confusing until you do.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1 — Make Code-OSS Feel Like the Real VS Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unlock the Official VS Marketplace
&lt;/h3&gt;

&lt;p&gt;By default, Code-OSS points to the Open VSX registry, not Microsoft's official Marketplace. A small config change fixes this and also renames the app to "Visual Studio Code" so everything feels native.&lt;/p&gt;

&lt;p&gt;Edit the product config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano /data/data/com.termux/files/usr/lib/code-oss/resources/app/product.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add or update these properties:&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;"nameShort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Visual Studio Code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nameLong"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Visual Studio Code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"applicationName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dataFolderName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"linuxIconName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"urlProtocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extensionsGallery"&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;"serviceUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://marketplace.visualstudio.com/_apis/public/gallery"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cacheUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://vscode.vo.msecnd.net/gallery"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"itemUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://marketplace.visualstudio.com/items"&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;"linkProtectionTrustedDomains"&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;"https://open-vsx.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://marketplace.visualstudio.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"https://vscode.vo.msecnd.net"&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;Save and restart Code-OSS. You now have the official Marketplace, the official name, and the &lt;code&gt;code&lt;/code&gt; command in your terminal. It's VS Code. On your phone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2 — Fix Language Servers That Don't Work
&lt;/h2&gt;

&lt;p&gt;The pattern for every broken language server is the same three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the correct binary via &lt;code&gt;apt&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remove the broken bundled binary that came with the extension&lt;/li&gt;
&lt;li&gt;Symlink the working system binary in its place&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's go through each one.&lt;/p&gt;




&lt;h3&gt;
  
  
  🦀 Rust — rust-analyzer
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Install the system binary:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;rust-analyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Remove the broken bundled binary:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; ~/.vscode/extensions/rust-lang.rust-analyzer-&lt;span class="k"&gt;*&lt;/span&gt;/server/rust-analyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3 — Symlink the working one:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which rust-analyzer&lt;span class="si"&gt;)&lt;/span&gt; ~/.vscode/extensions/rust-lang.rust-analyzer-&lt;span class="k"&gt;*&lt;/span&gt;/server/rust-analyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;If the &lt;code&gt;*&lt;/code&gt; wildcard doesn't work, run &lt;code&gt;ls ~/.vscode/extensions/&lt;/code&gt; to find the exact folder name and replace &lt;code&gt;*&lt;/code&gt; with the version number.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reload VS Code and open a &lt;code&gt;.rs&lt;/code&gt; file — autocomplete, type hints, and error checking should all be live. 🦀&lt;/p&gt;




&lt;h3&gt;
  
  
  🌙 Lua — lua-language-server
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Install the system binary:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;lua-language-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Remove the broken bundled binary:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; ~/.vscode/extensions/sumneko.lua-&lt;span class="k"&gt;*&lt;/span&gt;/server/bin/lua-language-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3 — Symlink the working one:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which lua-language-server&lt;span class="si"&gt;)&lt;/span&gt; ~/.vscode/extensions/sumneko.lua-&lt;span class="k"&gt;*&lt;/span&gt;/server/bin/lua-language-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open a &lt;code&gt;.lua&lt;/code&gt; file and watch IntelliSense spring to life. 🌙&lt;/p&gt;




&lt;h3&gt;
  
  
  🐛 CodeLLDB — Native Debugger for Rust &amp;amp; C++
&lt;/h3&gt;

&lt;p&gt;This one has more moving parts because CodeLLDB bundles several binaries. Same approach, just more symlinks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Install the system binaries:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;codelldb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Remove all the broken bundled binaries at once:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.vscode/extensions/vadimcn.vscode-lldb-&lt;span class="k"&gt;*&lt;/span&gt;/adapter/codelldb &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.vscode/extensions/vadimcn.vscode-lldb-&lt;span class="k"&gt;*&lt;/span&gt;/lldb/bin/lldb &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.vscode/extensions/vadimcn.vscode-lldb-&lt;span class="k"&gt;*&lt;/span&gt;/lldb/bin/lldb-server &lt;span class="se"&gt;\&lt;/span&gt;
  ~/.vscode/extensions/vadimcn.vscode-lldb-&lt;span class="k"&gt;*&lt;/span&gt;/lldb/bin/lldb-argdumper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3 — Symlink all four system binaries:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which codelldb&lt;span class="si"&gt;)&lt;/span&gt;       ~/.vscode/extensions/vadimcn.vscode-lldb-&lt;span class="k"&gt;*&lt;/span&gt;/adapter/codelldb
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which lldb&lt;span class="si"&gt;)&lt;/span&gt;           ~/.vscode/extensions/vadimcn.vscode-lldb-&lt;span class="k"&gt;*&lt;/span&gt;/lldb/bin/lldb
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which lldb-server&lt;span class="si"&gt;)&lt;/span&gt;    ~/.vscode/extensions/vadimcn.vscode-lldb-&lt;span class="k"&gt;*&lt;/span&gt;/lldb/bin/lldb-server
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which lldb-argdumper&lt;span class="si"&gt;)&lt;/span&gt; ~/.vscode/extensions/vadimcn.vscode-lldb-&lt;span class="k"&gt;*&lt;/span&gt;/lldb/bin/lldb-argdumper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set a breakpoint, hit F5, and you've got a working debugger. On Android. 🤯&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Troubleshooting — When Things Still Don't Work
&lt;/h2&gt;

&lt;p&gt;If a language server or debugger is still misbehaving after following the steps above, run through this checklist:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check that the symlinks actually exist:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; ~/.vscode/extensions/[extension-folder]/server/
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; ~/.vscode/extensions/[extension-folder]/adapter/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify the symlink targets are executable:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;file &lt;span class="si"&gt;$(&lt;/span&gt;which codelldb&lt;span class="si"&gt;)&lt;/span&gt;
file &lt;span class="si"&gt;$(&lt;/span&gt;which lldb&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Reload the language server without restarting VS Code:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;Ctrl+Shift+P&lt;/code&gt; → type &lt;code&gt;Restart Language Server&lt;/code&gt; → hit Enter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check for error details:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open the Output panel (&lt;code&gt;Ctrl+Shift+U&lt;/code&gt;) and select the language server from the dropdown. The error messages there are usually very specific and point right to the problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Quick Recap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language / Tool&lt;/th&gt;
&lt;th&gt;Package to Install&lt;/th&gt;
&lt;th&gt;What You Symlink&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rust-analyzer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;server/rust-analyzer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lua&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lua-language-server&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;server/bin/lua-language-server&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CodeLLDB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;codelldb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;adapter/codelldb&lt;/code&gt; + 3 lldb binaries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The pattern never changes: &lt;strong&gt;apt install → rm broken binary → ln -s system binary&lt;/strong&gt;. Once you understand this, you can apply it to any other language server that breaks in the future.&lt;/p&gt;




&lt;h2&gt;
  
  
  📁 All Configs Live in the Dotfiles Repo
&lt;/h2&gt;

&lt;p&gt;The full setup, including a curated list of recommended VS Code extensions for Termux, lives here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👉 &lt;a href="https://github.com/GourangaDasSamrat/dotfiles" rel="noopener noreferrer"&gt;github.com/GourangaDasSamrat/dotfiles&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check &lt;code&gt;docs/vscode/&lt;/code&gt; for both this setup guide and the full extensions list.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 You Now Have a Real Dev Environment on Android
&lt;/h2&gt;

&lt;p&gt;A working VS Code with IntelliSense, language servers, and a native debugger — all running on your phone without any root, emulation, or cloud tricks.&lt;/p&gt;

&lt;p&gt;Whether you're coding Rust on your commute or debugging Lua on your lunch break, your Android is now a legitimate development machine.&lt;/p&gt;

&lt;p&gt;Go ship something. 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this helped, star the &lt;a href="https://github.com/GourangaDasSamrat/dotfiles" rel="noopener noreferrer"&gt;dotfiles repo&lt;/a&gt; on GitHub! ⭐&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;📖 Read the previous post in this series:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://dev.to/gouranga-das-khulna/turn-your-android-into-a-full-desktop-no-root-needed-4fl6"&gt;Turn Your Android Into a Full Desktop — No Root Needed&lt;/a&gt; — Install XFCE4 + Code-OSS on Termux from scratch, no root, no proot, no hacks.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>linux</category>
      <category>android</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Test coverage and what it can tell us</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 10 May 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/test-coverage-and-what-it-can-tell-us-4olm</link>
      <guid>https://dev.to/gouranga-das-khulna/test-coverage-and-what-it-can-tell-us-4olm</guid>
      <description>&lt;p&gt;When we write production-grade code, we want confidence that it behaves as expected. One of the main ways to achieve that is through unit tests — small automated checks verifying that specific parts of the code work correctly.&lt;/p&gt;

&lt;p&gt;Naturally, this raises a few questions: How many tests do we need? And how effective are they? A common answer is test coverage — a metric showing how much of the codebase is executed during testing.&lt;/p&gt;

&lt;p&gt;Many teams use test coverage as a quality gate: if the number drops below a threshold, new code can’t be merged. But these thresholds are often arbitrary — high enough to feel safe, yet low enough to be achievable. 75%, 80%, 85% — familiar numbers that might look meaningful but rarely are.&lt;/p&gt;

&lt;p&gt;Before relying on coverage as a quality signal, we should ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  What does test coverage actually tell us?&lt;/li&gt;
&lt;li&gt;  How useful is it as a metric?&lt;/li&gt;
&lt;li&gt;  Does a certain percentage guarantee well-tested code?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post explores those questions and shows why high coverage can still be misleading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deceiving coverage
&lt;/h2&gt;

&lt;p&gt;For a start, let’s write a simple function that calculates a discount multiplier based on user age and activity status:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  For users under 18 years old, we give a 10% discount (multiplier 0.9).&lt;/li&gt;
&lt;li&gt;  For inactive users, we apply a 20% discount (multiplier 0.8).&lt;/li&gt;
&lt;li&gt;  For users who are both under 18 and inactive, we apply both discounts (multiplier 0.72).&lt;/li&gt;
&lt;li&gt;  For all other users, no discount is applied (multiplier 1.0).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the code for these requirements (I’ve chosen Go, but the language itself is not important here):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;CalcDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userAge&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isUserActive&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;discountMul&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;userAge&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;discountMul&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="m"&gt;0.9&lt;/span&gt; &lt;span class="c"&gt;// 10% discount for minors&lt;/span&gt;
    &lt;span class="p"&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;isUserActive&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;discountMul&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="m"&gt;0.8&lt;/span&gt; &lt;span class="c"&gt;// 20% discount for inactive users&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;discountMul&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s worth noting: this function is really simple, but that’s intentional. I want to have something very simple to make my points clear. Later, I will analyze the code to devise better test cases.&lt;/p&gt;

&lt;p&gt;Now, let’s write some tests for this function. And since we are going to talk about test coverage, let’s measure it as well — and use the test coverage as a metric:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"math"&lt;/span&gt;
    &lt;span class="s"&gt;"testing"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestCalcDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;TestCase&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;UserAge&lt;/span&gt;      &lt;span class="kt"&gt;int&lt;/span&gt;
        &lt;span class="n"&gt;IsUserActive&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
        &lt;span class="n"&gt;Expected&lt;/span&gt;     &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;testCases&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Test Case 1 - user age &amp;lt; 18 and user is inactive&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserAge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IsUserActive&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Expected&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.72&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c"&gt;// Test Case 2 - user age ≥ 18 and user is active&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserAge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IsUserActive&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Expected&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c"&gt;// Test Case 3 - user age &amp;lt; 18 and user is active&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserAge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IsUserActive&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Expected&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c"&gt;// Test Case 4 - user age ≥ 18 and user is inactive&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;UserAge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IsUserActive&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Expected&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testCase&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;testCases&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;testCase&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;testCase&lt;/span&gt;
        &lt;span class="n"&gt;testCaseName&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"%d-%t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsUserActive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testCaseName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;CalcDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsUserActive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Expected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;epsilon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0.00001&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;epsilon&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Expected %v, got %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testCase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’m going to run these tests with different sets of test cases and measure coverage:-examples/code-1 0.211s&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;go &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-covermode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;count &lt;span class="nt"&gt;-coverprofile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/null
&lt;span class="go"&gt;PASS
coverage: 100.0% of statements
ok      github.com/kapitanov/personal-blog/posts/code-examples/code-1   0.211s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My end goal for now is to reach 100% coverage, and I’m not going to look into the function code itself while writing the tests. Yes, it’s really simple, but let’s pretend it’s more complex — too complex to properly analyze manually. Thus, we’d have to rely on code coverage.&lt;/p&gt;

&lt;p&gt;I’m going to add test cases one by one and measure coverage after each addition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Without any tests, we have zero coverage, which makes sense.&lt;/li&gt;
&lt;li&gt;  With only one test (&lt;strong&gt;Test Case 1&lt;/strong&gt;), we already have 100% test coverage! This might look correct at first glance — as we cover both&lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; branches of each &lt;code&gt;if&lt;/code&gt; statement. But requirements-wise, we still don't have test cases for the remaining scenarios.&lt;/li&gt;
&lt;li&gt;  Adding more test cases does not change coverage — it remains at 100%.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, if I relied on test coverage as a metric and had a 100% coverage threshold (and the code were too complex to analyze manually), I would end up with a false sense of security — thinking that my function is properly tested while it’s not even remotely so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Digging deeper
&lt;/h2&gt;

&lt;p&gt;To unveil the mystery, let’s put the statements onto a call graph and analyze which branches are covered by which test cases:&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%2Fotq53ok9bo0a4ij0dmt7.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%2Fotq53ok9bo0a4ij0dmt7.png" alt="captionless image" width="726" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an example, I’ve highlighted &lt;strong&gt;Test Case 1&lt;/strong&gt; in the graph — and we can clearly see that it only covers 25% of the entire call graph! Now it’s clear: to properly test the function, we need to cover all branches of the call graph, so we need exactly four test cases to cover all branches.&lt;/p&gt;

&lt;p&gt;As you might have guessed, there are different types of code coverage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Statement coverage&lt;/strong&gt; — measures whether each statement in the code was executed. This is what we measured in the previous examples.
Even a single test case was enough to achieve 100% statement coverage.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Branch coverage&lt;/strong&gt; — measures whether each branch ( &lt;code&gt;true&lt;/code&gt;/ &lt;code&gt;false&lt;/code&gt;) of control structures (if, switch, for) was executed. For our example, &lt;strong&gt;Test Case 1&lt;/strong&gt; would cover two branches - the &lt;code&gt;true&lt;/code&gt; branch of the first &lt;code&gt;if&lt;/code&gt; and the &lt;code&gt;false&lt;/code&gt; branch of the second &lt;code&gt;if&lt;/code&gt; - out of a total of four branches, giving us 50% branch coverage.
Out of curiosity — we could get 100% branch coverage with just two test cases: &lt;strong&gt;Test Case 1&lt;/strong&gt; — user age &amp;lt; 18 and user is inactive, and &lt;strong&gt;Test Case 2&lt;/strong&gt; — user age ≥ 18 and user is active.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Path coverage&lt;/strong&gt; — measures whether all possible paths through the code were executed. In our example, we have four possible paths through the function, which means that &lt;strong&gt;Test Case 1&lt;/strong&gt; only covers one out of four paths, resulting in 25% path coverage.
We would need all four test cases to achieve 100% path coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most testing tools provide statement coverage; some might provide branch coverage — but as we have seen, neither of these types of coverage guarantees a proper level of verification.&lt;/p&gt;

&lt;p&gt;Only path coverage may guarantee that all possible scenarios were tested. But is it feasible to achieve path coverage in real life? Let’s take a look at another code example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"slices"&lt;/span&gt;
&lt;span class="c"&gt;// MinOf returns the minimum value from a slice of integers.&lt;/span&gt;
&lt;span class="c"&gt;// It doesn't allow empty slices as input.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;MinOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"empty slice"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;slices&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;xs&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function has two branches — one for empty slices and one for non-empty slices. So, would it be enough to have two test cases — one with an empty slice and one with a non-empty slice?&lt;/p&gt;

&lt;p&gt;The answer is no — because the &lt;code&gt;slices.Sort&lt;/code&gt; function itself has branches and paths that we don't control. Moreover, it's a library function - we don't know its implementation details, and they might change even between minor releases of the toolchain.&lt;/p&gt;

&lt;p&gt;And finally, let’s take a look at a slightly trickier example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ComplexCondition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;c&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="no"&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="no"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It seems that there are only two possible execution paths here — one where the condition is true and one where it’s false. But in reality, there are four possible combinations of input values (a, b, c)! Let’s rewrite the condition to make it more explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ComplexConditionExplicit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we see — we need four test cases to cover all possible paths through the function. This unfortunately means that even with 100% path coverage, we might need to write more tests than we initially thought.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and a few thoughts
&lt;/h2&gt;

&lt;p&gt;Generally, test coverage is a useful metric to have — it can help us identify untested parts of the code.&lt;/p&gt;

&lt;p&gt;But we should be aware of its limitations: even 100% statement or branch coverage does not guarantee that our code is properly tested. In fact, it does not even come close to guaranteeing that.&lt;/p&gt;

&lt;p&gt;At the same time, achieving 100% path coverage is often infeasible. Even if we manage to achieve it — our tests won’t survive any code changes.&lt;/p&gt;

&lt;p&gt;Thus, I recommend following a simple rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Until you have 100% coverage of the&lt;/em&gt; testable &lt;em&gt;parts of your codebase, you do have untested code. Once you have 100% coverage of the&lt;/em&gt; testable &lt;em&gt;parts of your codebase, you still might have untested code.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are a few steps to help you follow this rule:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; **Not every bit of code needs to be tested.
**Identify critical parts of your codebase that require proper testing. It’s likely you won’t even need tests for infrastructure code, glue code, and similar.
Do you really need to unit-test your logger setup or HTTP server initialization? Probably not — these parts of your codebase should be tested implicitly during integration testing stages.
Do you need to unit-test your business logic? Most likely, yes — these parts are critical and should be properly tested.
Write test scripts that calculate test coverage for these critical parts only. Even if some other units are indirectly covered by these tests — their coverage should not affect the resulting number.&lt;/li&gt;
&lt;li&gt; **Aim for 100% (full) coverage of the testable parts of your code.
**Having less than 100% (as we observed above) guarantees you don’t have well-tested code! 100% test coverage, on the other hand, means nothing — you still have to carefully design your tests and test cases. Thus, you should aim for 100% coverage, but not rely on it.&lt;/li&gt;
&lt;li&gt; **Be pragmatic.
**You won’t be able to achieve 100% all the time — often you’ll have lines of code that are not testable. In Go, it would be really painful (and usually unnecessary) to properly test all the error-handling &lt;code&gt;if err { return err }&lt;/code&gt; lines. Leave these lines untested - otherwise, you might end up wasting time writing fragile tests for code that has no business value.
Still, aim for 100% — if you have 95% coverage, it means that you have untested code. If you do — make sure you know which code is untested and why.
Review code coverage regularly — for each pull request, for example. You should pay extra attention to source code lines that belong to the critical parts of the codebase and are not covered by tests.&lt;/li&gt;
&lt;li&gt; **Don’t rely on code coverage thresholds.
**Don’t set arbitrary thresholds like 75%, 80%, or 85% — they are meaningless.
Don’t set a 100% threshold either — it’s often infeasible to achieve.
Don’t set different thresholds for different parts of the codebase — that’s meaningless as well.
Don’t set a “coverage should never decrease” rule — it doesn’t make sense.&lt;/li&gt;
&lt;li&gt; **Unit tests are never enough.
**Imagine that you have managed to achieve 100% path coverage of your entire codebase (somehow). Would it guarantee that your code works as expected? The answer is no — even totally correct code might fail in production due to misconfiguration, network issues, hardware failures, etc.
Thus, you should also have integration tests, end-to-end tests, and other types of tests. Unit tests (and their coverage) are merely a tool — one of the tools you should keep on your belt.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These recommendations are obviously opinionated; however, I personally follow them in my projects and find them useful.&lt;/p&gt;

&lt;p&gt;Hope you find them useful as well!&lt;/p&gt;

</description>
      <category>go</category>
      <category>unittest</category>
      <category>software</category>
    </item>
    <item>
      <title>Turn Your Android Into a Full Desktop — No Root Needed 🚀</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sat, 09 May 2026 05:06:30 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/turn-your-android-into-a-full-desktop-no-root-needed-4fl6</link>
      <guid>https://dev.to/gouranga-das-khulna/turn-your-android-into-a-full-desktop-no-root-needed-4fl6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Your pocket is hiding a surprisingly powerful computer. Let's unlock it.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most people use Termux to run a few scripts or compile some code. But what if you could run a &lt;strong&gt;full XFCE4 desktop environment&lt;/strong&gt; — with a taskbar, app launcher, file manager, browser, and VS Code — right on your Android phone? No root. No hacks. Just pure Linux power in your palm.&lt;/p&gt;

&lt;p&gt;This is exactly what the &lt;strong&gt;&lt;a href="https://github.com/GourangaDasSamrat/dotfiles" rel="noopener noreferrer"&gt;GourangaDasSamrat/dotfiles&lt;/a&gt;&lt;/strong&gt; repo makes effortlessly possible. Let's set it up step by step.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 What You'll End Up With
&lt;/h2&gt;

&lt;p&gt;A real, working Linux desktop on Android featuring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;XFCE4&lt;/strong&gt; — a fast, lightweight desktop environment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firefox&lt;/strong&gt; — full desktop browser&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code (code-oss)&lt;/strong&gt; — your favourite editor, on your phone&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rofi app launcher&lt;/strong&gt; — blazing-fast app search with &lt;code&gt;Ctrl+Space&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PulseAudio&lt;/strong&gt; — actual working audio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Debian container&lt;/strong&gt; (via proot) for running any Linux software&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ What You Need Before Starting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An Android phone (Android 7+)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://f-droid.org/packages/com.termux/" rel="noopener noreferrer"&gt;Termux&lt;/a&gt;&lt;/strong&gt; — install from F-Droid (NOT the Play Store version)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/termux/termux-x11/releases" rel="noopener noreferrer"&gt;Termux:X11&lt;/a&gt;&lt;/strong&gt; — the display server app&lt;/li&gt;
&lt;li&gt;A stable internet connection for the initial setup&lt;/li&gt;
&lt;li&gt;~3–4 GB of free storage&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Install both Termux and Termux:X11 from F-Droid or GitHub releases. The Play Store versions are outdated and will cause problems.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📦 Step 1 — Grant Storage &amp;amp; Update Termux
&lt;/h2&gt;

&lt;p&gt;Open Termux and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;termux-setup-storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tap &lt;strong&gt;Allow&lt;/strong&gt; when Android asks for storage permission. Then update your packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkg update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pkg upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grab a coffee — this takes a few minutes the first time. ☕&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Step 2 — Install the Desktop Stack
&lt;/h2&gt;

&lt;p&gt;Now install everything you need in one go. This installs &lt;strong&gt;git first&lt;/strong&gt;, then X11 support, XFCE4, PulseAudio, and a bunch of useful apps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add required repos and core packages (git is installed here first!)&lt;/span&gt;
pkg &lt;span class="nb"&gt;install &lt;/span&gt;git curl wget x11-repo tur-repo termux-x11-nightly pulseaudio &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Apps: browser, editor, image viewer, calculator&lt;/span&gt;
apt &lt;span class="nb"&gt;install &lt;/span&gt;firefox code-oss mousepad eog galculator pinentry-gnome3 &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# XFCE4 and all the good plugins&lt;/span&gt;
apt &lt;span class="nb"&gt;install &lt;/span&gt;xfce4 xfce4-whiskermenu-plugin xfce4-clipman-plugin &lt;span class="se"&gt;\&lt;/span&gt;
  xfce4-screenshooter xfce4-docklike-plugin xfce4-panel-profiles &lt;span class="se"&gt;\&lt;/span&gt;
  xfce4-taskmanager &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This installs quite a lot, so be patient and keep Termux open. If anything fails, re-run the same command — it picks up where it left off.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📥 Step 3 — Clone the Dotfiles Repo
&lt;/h2&gt;

&lt;p&gt;Now that git is installed, grab the dotfiles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/GourangaDasSamrat/dotfiles ~/dotfiles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This repo contains everything pre-configured — startup scripts, XFCE4 settings, tmux config, and desktop launch logic. You don't have to figure out any of it from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Step 4 — Set Up the Startup Script
&lt;/h2&gt;

&lt;p&gt;The dotfiles repo includes a ready-made startup script that handles everything: killing old X11 processes, starting PulseAudio, launching Termux:X11, and booting XFCE4.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; ~/dotfiles/docs/termux/native-desktop-start.sh ~/start.sh
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/start.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🖥️ Step 5 — Launch Your Desktop!
&lt;/h2&gt;

&lt;p&gt;This is the moment. Run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The script will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start PulseAudio for audio support&lt;/li&gt;
&lt;li&gt;Fire up the Termux:X11 display server&lt;/li&gt;
&lt;li&gt;Open the Termux:X11 app automatically&lt;/li&gt;
&lt;li&gt;Launch a full XFCE4 desktop session&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Switch to the &lt;strong&gt;Termux:X11 app&lt;/strong&gt; — and there's your desktop. 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  ⌨️ Keyboard Shortcuts Worth Memorising
&lt;/h2&gt;

&lt;p&gt;Once you're in the desktop, these shortcuts will make your life much easier:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Shortcut&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Open App Launcher (Rofi)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Ctrl + Space&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open Whisker Menu&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Super&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open Clipboard History&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Super + Alt + V&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🐧 Bonus: Add a Full Debian Container (Optional but Awesome)
&lt;/h2&gt;

&lt;p&gt;Want to &lt;code&gt;apt install&lt;/code&gt; literally anything from the Debian repos? Add a proot Debian container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pkg &lt;span class="nb"&gt;install &lt;/span&gt;proot-distro &lt;span class="nt"&gt;-y&lt;/span&gt;
proot-distro &lt;span class="nb"&gt;install &lt;/span&gt;debian
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then log in with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;proot-distro login debian
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside, you can install packages, set up users, configure your timezone, and run server software — all from within your Android:&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;# Inside Debian container&lt;/span&gt;
apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
apt &lt;span class="nb"&gt;install sudo &lt;/span&gt;git curl wget &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Set timezone (example: Asia/Dhaka)&lt;/span&gt;
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-sf&lt;/span&gt; /usr/share/zoneinfo/Asia/Dhaka /etc/localtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even symlink your Debian home folder to Termux's filesystem for easy file sharing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /data/data/com.termux/files/usr/var/lib/proot-distro/installed-rootfs/debian/home/YOUR_USER ~/Developer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎨 Personalise Your Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Change the Termux Welcome Message
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano &lt;span class="nv"&gt;$PREFIX&lt;/span&gt;/etc/motd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write anything you want — a quote, ASCII art, a dashboard. It shows every time you open Termux.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure GPG for Git Signing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano ~/.gnupg/gpg-agent.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;pinentry&lt;/span&gt;-&lt;span class="n"&gt;program&lt;/span&gt; /&lt;span class="n"&gt;data&lt;/span&gt;/&lt;span class="n"&gt;data&lt;/span&gt;/&lt;span class="n"&gt;com&lt;/span&gt;.&lt;span class="n"&gt;termux&lt;/span&gt;/&lt;span class="n"&gt;files&lt;/span&gt;/&lt;span class="n"&gt;usr&lt;/span&gt;/&lt;span class="n"&gt;bin&lt;/span&gt;/&lt;span class="n"&gt;pinentry&lt;/span&gt;-&lt;span class="n"&gt;gnome3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔁 Every Time You Want to Start the Desktop
&lt;/h2&gt;

&lt;p&gt;Just open Termux and run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;That's it. Your full desktop spins up in seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Why XFCE4?
&lt;/h2&gt;

&lt;p&gt;XFCE4 is the &lt;strong&gt;perfect choice&lt;/strong&gt; for mobile hardware. It's:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lightweight&lt;/strong&gt; — won't make your phone lag or overheat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable&lt;/strong&gt; — rock solid, no random crashes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Highly customisable&lt;/strong&gt; — themes, panels, plugins, everything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Familiar&lt;/strong&gt; — feels like a real desktop OS immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compared to heavier alternatives like GNOME or KDE, XFCE4 runs smoothly even on mid-range phones.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Pro Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep Termux awake:&lt;/strong&gt; Go to Android settings → Battery → Termux → set to "Unrestricted" to prevent the OS from killing your session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a Bluetooth keyboard &amp;amp; mouse&lt;/strong&gt; for the full desktop experience — it genuinely feels like a real computer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External display?&lt;/strong&gt; Some phones support video output via USB-C. Connect to a monitor and you've got a proper Linux workstation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tmux inside the terminal:&lt;/strong&gt; The dotfiles also include a full tmux config (&lt;code&gt;~/.tmux.conf&lt;/code&gt;) with mouse support, sensible shortcuts, and a clean status bar — great for running multiple terminal sessions inside the desktop.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📁 Everything Is in the Dotfiles Repo
&lt;/h2&gt;

&lt;p&gt;All the configs, scripts, and docs used in this guide live in one clean, well-organised repository:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👉 &lt;a href="https://github.com/GourangaDasSamrat/dotfiles" rel="noopener noreferrer"&gt;github.com/GourangaDasSamrat/dotfiles&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The native desktop startup script&lt;/li&gt;
&lt;li&gt;Tmux configuration&lt;/li&gt;
&lt;li&gt;VS Code extension list for Termux&lt;/li&gt;
&lt;li&gt;PRoot Debian setup guide&lt;/li&gt;
&lt;li&gt;GPG &amp;amp; Git configuration templates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Star it, fork it, and make it your own. 🌟&lt;/p&gt;




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

&lt;p&gt;A full Linux desktop on Android sounds like a geek fantasy — but with Termux, Termux:X11, and a solid dotfiles setup, it's completely real and surprisingly usable. Whether you're coding on the go, running a local server, or just geeking out, this setup delivers.&lt;/p&gt;

&lt;p&gt;Your phone is now also a computer. Go build something cool. 💻📱&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found this useful? Give the &lt;a href="https://github.com/GourangaDasSamrat/dotfiles" rel="noopener noreferrer"&gt;dotfiles repo&lt;/a&gt; a ⭐ on GitHub!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>android</category>
      <category>mobile</category>
    </item>
    <item>
      <title>How to Use Micro Frontends Without Regretting It</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 03 May 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/how-to-use-micro-frontends-without-regretting-it-aal</link>
      <guid>https://dev.to/gouranga-das-khulna/how-to-use-micro-frontends-without-regretting-it-aal</guid>
      <description>&lt;h2&gt;
  
  
  From Monolith Mess to MFE Freedom
&lt;/h2&gt;

&lt;p&gt;Your Angular app has ballooned into a beast — builds drag on forever, deployments become team-wide nightmares, and everyone’s stuck waiting on each other. It’s like cooking a feast for 20 in a cramped kitchen: one slow chopper holds up the line. We’ve all been there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Micro Frontends Flip the Script
&lt;/h3&gt;

&lt;p&gt;Micro frontends flip that script, especially in Angular. They carve your giant app into smaller, independent chunks that teams can build, test, and deploy solo — like Netflix doling out UI pieces without the mess. Angular’s Native Federation makes it seamless: ditch webpack woes for ES modules that share dependencies and lazy-load on demand.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Real Hook (and Headache)
&lt;/h3&gt;

&lt;p&gt;Here’s the real hook (and challenge): it’s less about code splits and more about dodging UI glitches or bundle bloat while gaining true autonomy. Whether you’re a dev testing the waters or a lead scoping enterprise scale, this article breaks down setups, best practices, and pitfalls — equipping you to scale like the pros, drama-free.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Micro Frontends Actually Make Sense (And When They Don’t)
&lt;/h2&gt;

&lt;p&gt;A massive ship with dozens of crew members tweaking their own decks without halting the whole vessel — that’s your frontend at scale. Chaotic? Absolutely. Monoliths suit small teams fine, but as complexity grows, micro frontends emerge as modular lifeboats, enabling independent team progress.&lt;/p&gt;

&lt;p&gt;Here’s the rub: most apps don’t need this firepower yet. I’ve seen teams jump into micro frontends too early, turning a simple project into a Frankenstein’s monster of mismatched UIs and bloated bundles. The real question? Does your business &lt;em&gt;need&lt;/em&gt; this level of decoupling, or are you just chasing a buzzword?&lt;/p&gt;

&lt;h3&gt;
  
  
  Spot the Chaos: Team Size Signals
&lt;/h3&gt;

&lt;p&gt;Start with the basics: team size and deployment drama. If you’ve got more than 30 developers split across features — like one squad on search, another on payments — micro frontends shine. They enable independent deploys, so the cart team ships weekly without rebuilding the entire app. No more “waiting on Bob’s login fix” nightmares.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nx Lifesaver: Skip MFEs Early
&lt;/h3&gt;

&lt;p&gt;But for smaller crews? Skip it. Angular’s monorepo magic with Nx handles growth beautifully first. Picture Nx as your smart toolbox: it enforces shared styles, lazy-loads modules, and deploys apps separately — all without the full MFE split. Many startups scale to 15 devs seamlessly with Nx. Escalate only for absolute autonomy, like blending React with Angular or isolated pipelines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Velocity Gold vs. Hidden Traps
&lt;/h3&gt;

&lt;p&gt;Sure, velocity skyrockets — teams own their turf, shipping faster. But risks lurk: UI drift (think buttons that look alien across pages), bundle bloat from duplicate libs, and that nagging coordination tax. It’s like inviting roommates who each decorate their room wild-west style; the house feels cohesive only with strict house rules.&lt;/p&gt;

&lt;p&gt;Enforce shared design systems and tools like Module Federation to share dependencies dynamically. Gains often crush cons in big orgs, but measure twice: velocity up, consistency down?&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%2F22cmo2qp7wp70ckz6fcw.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%2F22cmo2qp7wp70ckz6fcw.png" alt="Trade-offs Snapshot: MFEs at a Glance" width="725" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  E-Commerce Escape: Real Deploy Magic
&lt;/h3&gt;

&lt;p&gt;Take Ksolves’ fashion platform revamp: a U.S. e-commerce monolith choking on slow releases. They carved it into MFEs — catalog, cart, checkout — using Angular and Module Federation. Lazy loads, shared NgRx state, boom: 50% faster features, 35% quicker pages. Separate teams deployed freely, like clockwork. No more monolith roadblocks.&lt;/p&gt;

&lt;p&gt;Bottom line? Micro frontends aren’t a silver bullet — they’re for when monoliths crack under team scale. Assess needs honestly, lean on Angular’s strengths, and weigh those trades. Your app (and sanity) will thank you. Next time you’re eyeing that refactor, ask: autonomy or overkill?&lt;/p&gt;

&lt;h2&gt;
  
  
  Micro-Frontends Made Easy: Angular’s Native Federation Revolution
&lt;/h2&gt;

&lt;p&gt;Think of a massive enterprise app as a bustling shopping mall — each store runs independently, yet customers flow seamlessly between them. That’s micro-frontends (MFEs) in action. With Angular 17+, Native Federation makes this setup straightforward, ditching old headaches for speed and simplicity built right into Angular’s core.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Ditch the Old Ways?
&lt;/h3&gt;

&lt;p&gt;Let’s back up. Traditional monoliths? They’re that one giant codebase where every team steps on toes, deployments halt everything, and scaling feels like herding cats. Enter MFEs: break your app into bite-sized, team-owned chunks (a “shell” app plus “remote” modules like a products catalog). The catch? Older tools like webpack Module Federation added bloat and complexity. Native Federation, powered by esbuild, flips the script — native SSR support, CLI magic, and zero extra plugins. It’s Angular’s way of saying, “We’ve got this.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup That Feels Like Magic
&lt;/h3&gt;

&lt;p&gt;Here’s where it gets fun. Setup is a breeze with &lt;code&gt;@angular-architects/native-federation&lt;/code&gt;. Devs everywhere spin up demos quickly: &lt;code&gt;ng add @angular-architects/native-federation --project shell --type host&lt;/code&gt; for the host, then the same for remotes like "products." Instantly, &lt;code&gt;federation.config.js&lt;/code&gt; maps modules like a smart GPS. Nx workspaces take it further: &lt;code&gt;npx create-nx-workspace mfes&lt;/code&gt;, generate shell and remotes, serve—and proxies kill CORS woes effortlessly.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Singleton Superpower Unleashed
&lt;/h3&gt;

&lt;p&gt;The real hero? Dependency sharing. Duplicates are the silent killer — multiple Angular cores bloating your bundle like double-dipping on fries. Native Federation shares them as singletons by default: &lt;code&gt;shareAll({ singleton: true })&lt;/code&gt; in your config. Explicitly lock RxJS or Router too: &lt;code&gt;{ singleton: true, strictVersion: true }&lt;/code&gt;. It's like everyone at the party sharing one killer playlist instead of blasting their own. Multi-version libs? Tread carefully—eager load if clashes arise, or risk runtime drama.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy-Load Like a Pro
&lt;/h3&gt;

&lt;p&gt;Hands-on time. Lazy-load that products MFE in your shell routes:&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;loadChildren&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products/Module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ProductsModule&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;Or dynamically: &lt;code&gt;loadRemoteModule({ remoteEntry: 'http://localhost:4201/remoteEntry.js', exposedModule: './Module' })&lt;/code&gt;. Hit serve, navigate to &lt;code&gt;/products&lt;/code&gt;—watch it load on-demand, sharing singletons flawlessly. No full rebuilds. Pure joy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your App, Future-Proofed
&lt;/h3&gt;

&lt;p&gt;Why does this matter? In a world of distributed teams, Native Federation scales your app &lt;em&gt;and&lt;/em&gt; your sanity. Deployment independence means UI teams ship UI without backend waits. SSR keeps SEO happy. And as Angular evolves, you’re future-proofed — no webpack lock-in.&lt;/p&gt;

&lt;p&gt;Think of it like modular Lego: build grand castles, swap bricks anytime. Whether you’re a manager eyeing team velocity or a dev craving clean code, Native Federation delivers. Dive in — your mall just got a glow-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoiding Pitfalls and Regrets in Angular Micro Frontends
&lt;/h2&gt;

&lt;p&gt;You’re finally cruising down the highway in your shiny new Micro Frontends (MFE) setup with Angular’s Module Federation. Everything’s smooth — until suddenly, your app feels like it’s dragging a trailer full of bricks. Performance tanks, buttons look different across pages, and state glitches make users scratch their heads. Sound familiar? I’ve been there, refactoring a bloated monolith into MFEs only to realize I’d traded one headache for three. The good news? These pitfalls are avoidable with a few smart moves. Let’s unpack them like we’re grabbing coffee and swapping war stories.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dodge the Performance Brick Wall
&lt;/h3&gt;

&lt;p&gt;First off, performance hits can sneak up fast. Without lazy loading, you’re dumping every MFE into the initial bundle — like inviting the whole party to brunch when you just need coffee. Instead, load remotes dynamically: only pull in what users need, when they need it. Pair that with strict dependency sharing. Module Federation’s &lt;code&gt;share()&lt;/code&gt; config lets you expose Angular core, RxJS, or even your UI library once, slashing duplicates. Skip the fluff with &lt;code&gt;shareAll({ singleton: true, strictVersion: true, requiredVersion: 'auto' })&lt;/code&gt;. And don't sleep on CORS woes—those cross-origin asset blocks? Whip up a reverse proxy in &lt;code&gt;proxy.conf.json&lt;/code&gt; to route everything through your dev server. Pro tip: Monitor bundle sizes religiously with tools like BundleMon hooked into your CI pipeline. One spike, and you'll get an alert before launch day drama.&lt;/p&gt;

&lt;h3&gt;
  
  
  Banish UI Frankenstein Nightmares
&lt;/h3&gt;

&lt;p&gt;UI consistency is another gremlin. Picture your app as a mismatched wardrobe: one MFE rocks neon buttons, another sticks to grayscale. Fix it with a federated design system — Angular Material works beautifully when shared as a remote entry. Everyone pulls from the same stylish pot, no NPM version wars. Draw domain-driven boundaries too, using Nx workspace tags or Angular’s &lt;code&gt;providedIn: 'root'&lt;/code&gt; to keep features isolated yet harmonious. It's like giving each team their own kitchen but one shared spice rack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tame the State and Routing Beasts
&lt;/h3&gt;

&lt;p&gt;State and routing? Tricky beasts. Cross-MFE sync screams for NgRx: slice your store by domain, use facades for clean APIs, and dispatch custom events for navigation handoffs. Say a remote MFE needs to trigger a shell route — boom, &lt;code&gt;childRouteChanged&lt;/code&gt; event handles it without tight coupling. For versioning, dynamic manifests (&lt;code&gt;mf.manifest.json&lt;/code&gt;) let you hot-swap remotes at runtime, dodging build-time lock-ins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Slash 50% Off Feature Delivery Time
&lt;/h3&gt;

&lt;p&gt;Take this real-world win: A team migrated their monolith to MFEs and slashed feature delivery time by 50%. Independent deploys? Check. Lazy loads trimmed initial times by 35%. But early CORS snarls and state leaks nearly derailed it — until proxies and shared libs saved the day.&lt;/p&gt;

&lt;p&gt;The takeaway? MFEs aren’t set-it-and-forget-it. Treat them like a high-performance engine: tune for speed, align the parts, and test relentlessly. Skip these steps, and regrets pile up. Nail them, and you’re not just building apps — you’re future-proofing your frontend revolution. Your users (and stakeholders) will thank you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Micro-Frontend Success
&lt;/h2&gt;

&lt;p&gt;Micro-frontends (MFEs) let you scale Angular apps like snapping together specialized Lego pieces instead of wrestling one giant brick. They’re powerful, but success demands smart moves. Jumping in without a plan risks chaos — frustrating, error-prone, and ready to topple. Let’s break down the practices that make it smooth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start Small, Win Big
&lt;/h3&gt;

&lt;p&gt;The golden rule? &lt;strong&gt;Start small with pilots.&lt;/strong&gt; Don’t overhaul your entire monorepo overnight. Pick 2–3 MFEs — say, a user dashboard, product catalog, and checkout flow — and test them in a controlled monorepo setup using tools like Nx. This keeps code sharing easy (think shared UI libraries) while letting each team own their domain. Automate CI/CD pipelines per remote MFE with Module Federation magic: independent builds and deploys mean one team’s hiccup doesn’t halt the show. It’s like fixing a car while it’s still running, but with seatbelts — safe and iterative.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ditch Props, Master Events
&lt;/h3&gt;

&lt;p&gt;Communication is where most MFE dreams crumble, so &lt;strong&gt;lean on event buses and contracts, not direct props.&lt;/strong&gt; Direct props create tight coupling and version hell. Instead, define lightweight contracts: stable events with a unique ID and minimal data, published via a shared message bus. MFEs listen anonymously, staying blissfully unaware of each other’s guts. Version independently, evolve contracts slowly with schema validation, and watch breaking changes vanish. No more “my update broke your UI” drama.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test Smart, Deploy Fearless
&lt;/h3&gt;

&lt;p&gt;Testing and deployment demand discipline too. &lt;strong&gt;Run independent pipelines for units and integrations, but E2E across the shell.&lt;/strong&gt; Each MFE gets its own fast tests, while a parent pipeline catches shell-level glitches — triggering rollbacks if needed. Crave speed? Lazy-load remotes and embrace SSR with smart hydration to dodge mismatches and slash load times. Progressive hydration ensures the server-rendered shell hydrates client-side MFEs without jank, keeping users happy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ksolves: 35% Faster Loads
&lt;/h3&gt;

&lt;p&gt;Real-world proof? Ksolves nailed it with an e-commerce giant. They splintered a monolithic Angular app into lazy-loaded MFEs for catalog, cart, and checkout. Result: 35% faster initial loads, 50% quicker feature rolls, and true team autonomy — all without UX fractures. Independent pipelines minimized risks, and a shared design system glued it together seamlessly.&lt;/p&gt;

&lt;p&gt;These practices aren’t checkboxes; they’re your roadmap to MFE mastery. Start small, communicate loosely, test rigorously, and scale confidently. Your Angular app will thank you — faster, more resilient, and ready for whatever growth throws your way. Who’s piloting their first MFE this week?&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready to Scale Smart?
&lt;/h2&gt;

&lt;p&gt;Wrapping up our deep dive into Micro Frontends (MFEs) with Angular and Nx, you’ve got the tools to build scalable, team-friendly apps without the headaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Power Trio: Key Takeaways
&lt;/h3&gt;

&lt;p&gt;Implement MFEs only when your project hits real scale — like multi-team setups demanding independent deploys and tech stacks. Otherwise, stick to monorepo libraries for Angular’s compile-time magic. Prioritize Native Federation for slick sharing of deps like Angular core and RxJS via &lt;code&gt;shareAll({})&lt;/code&gt;, cutting bundle bloat. Always enforce strict boundaries with clear exposes in &lt;code&gt;federation.config.js&lt;/code&gt; and lazy loads via &lt;code&gt;loadRemoteModule&lt;/code&gt; to sidestep regrets like sluggish perf (federation artifacts can drag dev builds) or UI drift across remotes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hands-On: Build Your Pilot
&lt;/h3&gt;

&lt;p&gt;Fire up an Nx workspace today: &lt;code&gt;npx create-nx-workspace@latest my-mfe --preset=apps&lt;/code&gt;, add Angular with &lt;code&gt;nx add @nx/angular&lt;/code&gt;, then generate a host and remote like &lt;code&gt;nx g @nx/angular:host apps/shell&lt;/code&gt; and &lt;code&gt;nx g @nx/angular:remote apps/mfe1 --host=shell&lt;/code&gt;. Serve with &lt;code&gt;nx serve shell --devRemotes=mfe1&lt;/code&gt; and tweak routes to lazy-load your MFE. Share your pilot wins (or epic fails) in the comments—perf metrics or boundary gotchas welcome!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>software</category>
    </item>
    <item>
      <title>I Spent Months Perfecting My Dotfiles So You Don't Have To — Here's Everything Inside</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Wed, 29 Apr 2026 10:45:06 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/i-spent-months-perfecting-my-dotfiles-so-you-dont-have-to-heres-everything-inside-1cjn</link>
      <guid>https://dev.to/gouranga-das-khulna/i-spent-months-perfecting-my-dotfiles-so-you-dont-have-to-heres-everything-inside-1cjn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Your terminal is where you live. Make it beautiful."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every developer has a dotfiles repo. Most of them are a pile of Gists half-remembered from 2019, a &lt;code&gt;.bashrc&lt;/code&gt; that's been copy-pasted between machines for years, and a VS Code settings file that's one merge conflict away from catastrophe.&lt;/p&gt;

&lt;p&gt;This one is different. I want to walk you through &lt;strong&gt;every real, working piece&lt;/strong&gt; of &lt;a href="https://github.com/GourangaDasSamrat/dotfiles" rel="noopener noreferrer"&gt;gourangadassamrat/dotfiles&lt;/a&gt; — not just the highlights reel, but the actual code, the design decisions, and the parts that took the most iteration to get right.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ The Bootstrap: One Command, Full Environment
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/GourangaDasSamrat/dotfiles.git ~/dotfiles
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/dotfiles/scripts &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;install.sh&lt;/code&gt; calls every module in &lt;code&gt;lib/&lt;/code&gt; in order. If you want to pick and choose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./setup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This drops you into a numbered menu of every &lt;code&gt;.sh&lt;/code&gt; file found recursively in &lt;code&gt;scripts/&lt;/code&gt; (excluding itself and &lt;code&gt;utils/&lt;/code&gt;). You pick by number — or type &lt;code&gt;all&lt;/code&gt;. No YAML, no external tooling, just bash.&lt;/p&gt;

&lt;p&gt;The brains behind cross-platform compatibility live in &lt;code&gt;utils/detect.sh&lt;/code&gt;, which determines your OS, available package manager (apt, brew, pacman), and sudo access. Every script in &lt;code&gt;lib/&lt;/code&gt; sources this. The result: the same &lt;code&gt;lib/packages.sh&lt;/code&gt; that runs &lt;code&gt;apt install&lt;/code&gt; on Ubuntu runs &lt;code&gt;brew install&lt;/code&gt; on macOS, transparently.&lt;/p&gt;

&lt;p&gt;Everything is symlinked into place using &lt;strong&gt;GNU Stow&lt;/strong&gt; — one call to &lt;code&gt;stow &amp;lt;module&amp;gt;&lt;/code&gt; and the directory structure inside that module folder maps directly onto &lt;code&gt;$HOME&lt;/code&gt;. Zero manual path management.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐚 The Shell: Nothing Is Left Unquestioned
&lt;/h2&gt;

&lt;p&gt;The zsh config lives under &lt;code&gt;zsh/.config/zsh/&lt;/code&gt; and is split into &lt;code&gt;core/&lt;/code&gt;, &lt;code&gt;functions/&lt;/code&gt;, &lt;code&gt;plugins/&lt;/code&gt;, and &lt;code&gt;user/&lt;/code&gt;. Here's what's actually in each.&lt;/p&gt;

&lt;h3&gt;
  
  
  core/
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;colors.zsh&lt;/code&gt;&lt;/strong&gt; — Defines &lt;code&gt;COLOR_HEADER&lt;/code&gt;, &lt;code&gt;COLOR_SUCCESS&lt;/code&gt;, &lt;code&gt;COLOR_ERROR&lt;/code&gt;, &lt;code&gt;COLOR_WARNING&lt;/code&gt;, &lt;code&gt;COLOR_TEXT&lt;/code&gt;, &lt;code&gt;COLOR_CURSOR&lt;/code&gt;, &lt;code&gt;COLOR_BORDER&lt;/code&gt;, &lt;code&gt;COLOR_NORMAL&lt;/code&gt;, &lt;code&gt;COLOR_RESET&lt;/code&gt; as ANSI escape sequences. Every function and alias in the repo uses these — the whole terminal has a consistent color palette, not just a theme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;env.zsh&lt;/code&gt;&lt;/strong&gt; — &lt;code&gt;DOTFILES&lt;/code&gt; path, &lt;code&gt;GOPATH&lt;/code&gt;, editor set to &lt;code&gt;nvim&lt;/code&gt;, &lt;code&gt;XDG_*&lt;/code&gt; base dirs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;history.zsh&lt;/code&gt;&lt;/strong&gt; — &lt;code&gt;HISTSIZE&lt;/code&gt;, &lt;code&gt;SAVEHIST&lt;/code&gt;, &lt;code&gt;setopt SHARE_HISTORY&lt;/code&gt;. Done correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  user/aliases.zsh
&lt;/h3&gt;

&lt;p&gt;A few highlights that deserve explanation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;eza&lt;/code&gt; aliases are conditional.&lt;/strong&gt; They only activate if &lt;code&gt;eza&lt;/code&gt; is actually in &lt;code&gt;$PATH&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;$+&lt;/span&gt;commands[eza]&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;alias ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'eza --color=always --long --git --no-filesize --icons=always --no-time --no-user --no-permissions'&lt;/span&gt;
  &lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;lt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'eza --tree -a -I "node_modules|.git"'&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;VS Code profile switching&lt;/strong&gt; is handled gracefully across &lt;code&gt;code&lt;/code&gt;, &lt;code&gt;code-oss&lt;/code&gt;, and &lt;code&gt;code-insiders&lt;/code&gt;. It detects which binary exists and aliases it correctly, then layers profile shortcuts on top — only if &lt;code&gt;code&lt;/code&gt; resolves at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;code-b&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "Backend Dev"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;code-f&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "Frontend Dev"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;code-g&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "Go Dev"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;code-c&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "C/C++ Dev"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;code-d&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "Database Dev"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;code-r&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "Rust Dev"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;code-l&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "Lua Dev"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;code-p&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "Python Dev"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;code-w&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'code --profile "Wiki Dev"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nine profiles. One alias each. &lt;strong&gt;Termux support&lt;/strong&gt; is included too — for those of us who develop on Android:&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; /data/data/com.termux &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;debian&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"TERM='xterm-256color' proot-distro login debian --user gouranga"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔧 user/overrides.zsh: &lt;code&gt;mkdir&lt;/code&gt; and &lt;code&gt;rm&lt;/code&gt; Reimagined
&lt;/h2&gt;

&lt;p&gt;These two rewrites are among my favorite parts of the whole repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;mkdir&lt;/code&gt; — Git-aware directory creation
&lt;/h3&gt;

&lt;p&gt;When you create a single directory, an interactive prompt appears — no fzf, just pure terminal keyboard input with &lt;code&gt;read -k1&lt;/code&gt; and ANSI escape sequences for arrow key detection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ◆  Initialize git repository in 'myproject'?
     Yes  › No
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use left/right arrows to toggle, Enter to confirm. If you say Yes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
git init &lt;span class="nt"&gt;-q&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"# &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; README.md
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: initialize repository with README"&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It quietly creates the repo, writes a README, and makes the first conventional commit — all in one &lt;code&gt;mkdir&lt;/code&gt; call. Creating multiple directories skips the prompt entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;rm&lt;/code&gt; — Confirm before you destroy
&lt;/h3&gt;

&lt;p&gt;Overrides &lt;code&gt;rm&lt;/code&gt; to first show you exactly what you're deleting (with 📁/📄 icons for directories vs files), then presents the same arrow-key Yes/No interface. Flags like &lt;code&gt;-rf&lt;/code&gt; still pass through after confirmation. Both overrides use &lt;code&gt;tput civis&lt;/code&gt; to hide the cursor during interaction and &lt;code&gt;trap 'tput cnorm' EXIT&lt;/code&gt; to restore it on exit or Ctrl+C.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔌 plugins/fzf.zsh: fzf Done Properly
&lt;/h2&gt;

&lt;p&gt;The fzf config ships two themes — Dracula and Catppuccin — as named functions that can be swapped by calling them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;_fzf_theme_dracula&lt;span class="o"&gt;()&lt;/span&gt;    &lt;span class="c"&gt;# active by default&lt;/span&gt;
_fzf_theme_catppuccin&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="c"&gt;# call to switch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each sets the full 8-color &lt;code&gt;FZF_DEFAULT_OPTS&lt;/code&gt; palette: fg, bg, hl, info, prompt, pointer, marker, spinner, header, border.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search uses &lt;code&gt;fd&lt;/code&gt; instead of &lt;code&gt;find&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FZF_DEFAULT_COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fd --hidden --strip-cwd-prefix --exclude .git"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tab completion previews&lt;/strong&gt; use &lt;code&gt;eza&lt;/code&gt; for directories and &lt;code&gt;bat&lt;/code&gt; for files. &lt;strong&gt;Context-aware completion&lt;/strong&gt; via &lt;code&gt;_fzf_comprun&lt;/code&gt; routes different commands to appropriate previews — &lt;code&gt;cd&lt;/code&gt; gets a directory tree, &lt;code&gt;ssh&lt;/code&gt; gets &lt;code&gt;dig {}&lt;/code&gt;, &lt;code&gt;export&lt;/code&gt;/&lt;code&gt;unset&lt;/code&gt; evaluates the variable value.&lt;/p&gt;




&lt;h2&gt;
  
  
  📡 functions/ — Custom Commands Written From Scratch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;apireq&lt;/code&gt; — A Full API Client in Your Terminal
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;apireq&lt;/code&gt; is the most complex function in the repo. It's a complete interactive HTTP client powered by &lt;code&gt;fzf&lt;/code&gt;, written entirely in zsh. No dependencies beyond &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;fzf&lt;/code&gt;, &lt;code&gt;bat&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt;, and optionally &lt;code&gt;python3&lt;/code&gt; for JSON validation.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Choose: &lt;strong&gt;Create new request&lt;/strong&gt; or &lt;strong&gt;Load saved &lt;code&gt;.http&lt;/code&gt; file&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Pick HTTP method via fzf&lt;/li&gt;
&lt;li&gt;Enter URL&lt;/li&gt;
&lt;li&gt;Multi-select with Space: Auth · Custom Headers · Query Params · Request Body&lt;/li&gt;
&lt;li&gt;Auth: Bearer Token or Basic Auth (password via &lt;code&gt;read -rs&lt;/code&gt;, no echo to terminal)&lt;/li&gt;
&lt;li&gt;Body: JSON (validated via &lt;code&gt;python3 -m json.tool&lt;/code&gt;), Raw Text, Form Data (urlencoded), or Multipart (supports file upload via &lt;code&gt;key=@/path/to/file&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Output: &lt;code&gt;auto&lt;/code&gt; (bat for headers + jq for JSON body), &lt;code&gt;bat&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt;, or &lt;code&gt;raw&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save as &lt;code&gt;.http&lt;/code&gt; file with an fzf folder picker that browses &lt;code&gt;$HOME&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;.http&lt;/code&gt; format is real — saved requests can be loaded, inspected in a preview pane, and optionally modified field-by-field (method, URL, headers, body) before re-sending.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;archive.zsh&lt;/code&gt; — Universal Pack/Unpack
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;extract()&lt;/code&gt; handles &lt;code&gt;tar.*&lt;/code&gt;, &lt;code&gt;tgz&lt;/code&gt;, &lt;code&gt;tbz2&lt;/code&gt;, &lt;code&gt;txz&lt;/code&gt;, and &lt;code&gt;zip&lt;/code&gt; via a clean case statement with colorized output using the &lt;code&gt;colors.zsh&lt;/code&gt; palette.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;compress()&lt;/code&gt; presents an fzf menu of 7 formats with human descriptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tar.gz   → Good balance, common
tar.bz2  → Better compression, slower
tar.xz   → Best compression, slowest
zip      → Cross-platform
7z       → High compression
gz       → Single file only
bz2      → Single file only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.gz&lt;/code&gt; and &lt;code&gt;.bz2&lt;/code&gt; correctly bail out with an error if you try to compress a directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;network.zsh&lt;/code&gt; — Three Genuinely Useful Web Commands
&lt;/h3&gt;

&lt;p&gt;All three are conditionally defined — they only load if their dependencies exist at shell startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;isup [url]&lt;/code&gt;&lt;/strong&gt; — Uses &lt;code&gt;httpie&lt;/code&gt; with &lt;code&gt;-F&lt;/code&gt; (follow redirects) and &lt;code&gt;-p=h&lt;/code&gt; (headers only) to check site status. Displays &lt;code&gt;✔ ONLINE [200 OK]&lt;/code&gt;, &lt;code&gt;⚠ ISSUE [301]&lt;/code&gt;, or &lt;code&gt;✘ OFFLINE&lt;/code&gt;. Extracts and shows the &lt;code&gt;Server:&lt;/code&gt; header value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;myip&lt;/code&gt;&lt;/strong&gt; — Fetches &lt;code&gt;ipinfo.io&lt;/code&gt; via httpie, parses the JSON with &lt;code&gt;grep -Po&lt;/code&gt;, and prints IP address, city + region, and ISP — all styled with the color palette.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;inspect [url]&lt;/code&gt;&lt;/strong&gt; — Fetches response headers filtered to security-relevant ones (&lt;code&gt;Server&lt;/code&gt;, &lt;code&gt;Content-Type&lt;/code&gt;, &lt;code&gt;X-Powered-By&lt;/code&gt;, &lt;code&gt;Cache-Control&lt;/code&gt;, &lt;code&gt;Strict-Transport-Security&lt;/code&gt;), then runs &lt;code&gt;openssl s_client&lt;/code&gt; to show SSL cert validity dates. Only defined when both &lt;code&gt;http&lt;/code&gt; and &lt;code&gt;openssl&lt;/code&gt; are available.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;utils.zsh&lt;/code&gt; — The Everyday Toolkit
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;serve [port]&lt;/code&gt;&lt;/strong&gt; — Python HTTP server with a full validation loop: ensures the port is numeric, 1–65535, and not already bound (&lt;code&gt;lsof -Pi :$port -sTCP:LISTEN&lt;/code&gt;). Prompts for another port if occupied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;timer &amp;lt;duration&amp;gt;&lt;/code&gt;&lt;/strong&gt; — Accepts raw seconds, &lt;code&gt;1h30m&lt;/code&gt;, &lt;code&gt;45m20s&lt;/code&gt;, or any combination. Renders a full-screen countdown: color-coded time display (green → yellow → red as it runs out), a 40-char block progress bar (&lt;code&gt;█░&lt;/code&gt;), a braille spinner, and elapsed time. On completion: terminal bell (&lt;code&gt;\a&lt;/code&gt;), &lt;code&gt;notify-send&lt;/code&gt; desktop notification, and system audio via &lt;code&gt;paplay&lt;/code&gt; or &lt;code&gt;aplay&lt;/code&gt; if available.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;backup &amp;lt;path&amp;gt;&lt;/code&gt;&lt;/strong&gt; — One command creates &lt;code&gt;folder_backup_20260429_142301.tar.gz&lt;/code&gt; with a precise timestamp.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;weather [city]&lt;/code&gt;&lt;/strong&gt; — Fetches &lt;code&gt;wttr.in/&amp;lt;city&amp;gt;?0mFq&amp;amp;format=v2&lt;/code&gt; — the v2 format gives a full readable weather card. Defaults to Khulna.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;t &amp;lt;command&amp;gt;&lt;/code&gt;&lt;/strong&gt; — Prefixes every output line from any command with &lt;code&gt;[YYYY-MM-DD HH:MM:SS]&lt;/code&gt; via &lt;code&gt;moreutils&lt;/code&gt;' &lt;code&gt;ts&lt;/code&gt;. Uses &lt;code&gt;stdbuf -oL -eL&lt;/code&gt; for real-time line-buffered output and &lt;code&gt;FORCE_COLOR=3&lt;/code&gt; to preserve colors in piped output. Defined only if &lt;code&gt;ts&lt;/code&gt; is installed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;expose [port] [ttl]&lt;/code&gt;&lt;/strong&gt; — Wraps &lt;code&gt;slim share&lt;/code&gt; with the same port validation as &lt;code&gt;serve&lt;/code&gt;. Exposes localhost to the internet. Optional &lt;code&gt;ttl&lt;/code&gt; argument passed through. Defined only if &lt;code&gt;slim&lt;/code&gt; is installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;security.zsh&lt;/code&gt; — Auto-Locking GPG
&lt;/h3&gt;

&lt;p&gt;Spawns a background daemon named &lt;code&gt;gpg-auto-lock-loop&lt;/code&gt; via &lt;code&gt;exec -a&lt;/code&gt; (so it's grep-able by name) that fires &lt;code&gt;gpg-connect-agent reloadagent /bye&lt;/code&gt; every 900 seconds — locking your GPG key cache. Checks for an existing instance before spawning so sourcing your config multiple times never creates duplicates.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;whois.zsh&lt;/code&gt; — Filtered WHOIS Lookup
&lt;/h3&gt;

&lt;p&gt;Defines a server map with keys &lt;code&gt;dp&lt;/code&gt; (whois.digitalplat.org), &lt;code&gt;iana&lt;/code&gt; (whois.iana.org), and &lt;code&gt;com&lt;/code&gt; (whois.verisign-grs.com):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dzw example.com           &lt;span class="c"&gt;# default server&lt;/span&gt;
dzw dp example.com        &lt;span class="c"&gt;# via digitalplat.org&lt;/span&gt;
dzw iana example.com      &lt;span class="c"&gt;# via IANA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output is filtered with &lt;code&gt;grep -E&lt;/code&gt; to useful fields only — Domain Name, Registrar, dates, Name Servers, Status — stripping all legal boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;chpwd.zsh&lt;/code&gt; — Smart Directory Change Hooks
&lt;/h3&gt;

&lt;p&gt;Three functions registered via &lt;code&gt;add-zsh-hook chpwd&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;_manage_python_venv&lt;/code&gt;&lt;/strong&gt; — Checks for &lt;code&gt;.venv&lt;/code&gt;, &lt;code&gt;venv&lt;/code&gt;, or &lt;code&gt;.env&lt;/code&gt; directories. Auto-activates on &lt;code&gt;cd&lt;/code&gt; in, auto-deactivates on &lt;code&gt;cd&lt;/code&gt; out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;_list_project_tools&lt;/code&gt;&lt;/strong&gt; — On every &lt;code&gt;cd&lt;/code&gt;, detects and lists available automation targets. &lt;code&gt;justfile&lt;/code&gt; → &lt;code&gt;just --list&lt;/code&gt;. &lt;code&gt;Makefile&lt;/code&gt; → awk-parsed targets. &lt;code&gt;package.json&lt;/code&gt; → &lt;code&gt;jq -r '.scripts | keys[]'&lt;/code&gt;. &lt;code&gt;docker-compose.yml&lt;/code&gt; → &lt;code&gt;docker compose ps --services&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;_auto_nvm_use&lt;/code&gt;&lt;/strong&gt; — Reads &lt;code&gt;.nvmrc&lt;/code&gt; and calls &lt;code&gt;nvm use&lt;/code&gt; automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;plugins/pass.zsh&lt;/code&gt; — Encrypted Secret Management
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;env-save &amp;lt;file&amp;gt; &amp;lt;pass-path&amp;gt;&lt;/code&gt;&lt;/strong&gt; — Reads a &lt;code&gt;.env&lt;/code&gt; file and pipes it into &lt;code&gt;pass insert -m&lt;/code&gt; at any path in the password store. Multi-line safe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;env-load &amp;lt;pass-path&amp;gt; [filename]&lt;/code&gt;&lt;/strong&gt; — Pulls secrets out of &lt;code&gt;pass&lt;/code&gt; into a local file (defaults to &lt;code&gt;.env&lt;/code&gt;). Verifies the path exists before writing. Prints line count on success.&lt;/p&gt;




&lt;h2&gt;
  
  
  🪟 tmux: Live Weather in the Status Bar
&lt;/h2&gt;

&lt;p&gt;The tmux config uses &lt;strong&gt;Catppuccin macchiato&lt;/strong&gt; with rounded window separators and status bar at the top, updating every second.&lt;/p&gt;

&lt;p&gt;The live weather widget:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set -ag status-right "#[fg=#b7bdf8,bg=#24273a] #[fg=#24273a,bg=#b7bdf8,bold]#(curl -s 'wttr.in/Khulna?format=%%c%%t' | tr -d '+')#[fg=#b7bdf8,bg=#24273a] "
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fetches the current condition icon and temperature from wttr.in every second. &lt;code&gt;tr -d '+'&lt;/code&gt; strips the leading &lt;code&gt;+&lt;/code&gt; from positive temperatures.&lt;/p&gt;

&lt;p&gt;Key bindings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prefix:         Ctrl+A
Splits:         | horizontal · - vertical (opens at current path)
Pane nav:       h·j·k·l (Vim) or Alt+Arrow (no prefix)
Window nav:     Alt+1–5 (no prefix needed)
Window reorder: &amp;lt; and &amp;gt; to swap left/right
Resize:         Prefix + H/J/K/L (repeatable with -r)
Zoom pane:      Prefix + m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Persistence:&lt;/strong&gt; &lt;code&gt;tmux-resurrect&lt;/code&gt; + &lt;code&gt;tmux-continuum&lt;/code&gt; auto-save every 5 minutes (&lt;code&gt;@continuum-save-interval '5'&lt;/code&gt;), restore on server start (&lt;code&gt;@continuum-restore 'on'&lt;/code&gt;), and capture pane contents (&lt;code&gt;@resurrect-capture-pane-contents 'on'&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  🖥️ VS Code: Nine Profiles, Every Extension Documented
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;docs/vscode/vscode-extensions.md&lt;/code&gt; documents every extension per profile:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Profile&lt;/th&gt;
&lt;th&gt;Formatter&lt;/th&gt;
&lt;th&gt;Key Extensions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Dracula, Error Lens, GitLens, Code Spell Checker, Commit Sage, Todo Tree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Prettier + ESLint&lt;/td&gt;
&lt;td&gt;Live Server, Pretty TS Errors, Tailwind IntelliSense&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Prettier + ESLint&lt;/td&gt;
&lt;td&gt;Thunder Client, Prisma, SQLTools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C/C++&lt;/td&gt;
&lt;td&gt;clangd&lt;/td&gt;
&lt;td&gt;clangd, Code Runner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;gopls + goimports&lt;/td&gt;
&lt;td&gt;Go (official), Code Runner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;prettier-sql&lt;/td&gt;
&lt;td&gt;Prettier SQL VSCode, SQLTools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;rust-analyzer&lt;/td&gt;
&lt;td&gt;rust-analyzer, Code Runner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lua&lt;/td&gt;
&lt;td&gt;sumneko&lt;/td&gt;
&lt;td&gt;Lua, Code Runner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wiki&lt;/td&gt;
&lt;td&gt;Prettier&lt;/td&gt;
&lt;td&gt;Prettier&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Font stack: &lt;strong&gt;Operator Mono&lt;/strong&gt; (italic keywords + ligatures) → Cartograph CF → JetBrains Mono.&lt;/p&gt;

&lt;p&gt;Custom snippets shipped: &lt;code&gt;cpp.json&lt;/code&gt; (competitive programming main, LeetCode template), &lt;code&gt;go.json&lt;/code&gt; (main, package, iferr, interface), &lt;code&gt;react-components.code-snippets&lt;/code&gt;, &lt;code&gt;clang-format.code-snippets&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✏️ Neovim: lazy.nvim + Custom Dashboard
&lt;/h2&gt;

&lt;p&gt;Managed by &lt;code&gt;lazy.nvim&lt;/code&gt;. Plugins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Mofiqul/dracula.nvim&lt;/code&gt; — Dracula with &lt;code&gt;italic_comment = true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nvim-lualine/lualine.nvim&lt;/code&gt; — statusline with &lt;code&gt;dracula-nvim&lt;/code&gt; theme&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;windwp/nvim-autopairs&lt;/code&gt; — auto-close brackets on &lt;code&gt;InsertEnter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;folke/todo-comments.nvim&lt;/code&gt; — highlights &lt;code&gt;TODO:&lt;/code&gt;, &lt;code&gt;FIXME:&lt;/code&gt;, &lt;code&gt;NOTE:&lt;/code&gt; etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rhysd/committia.vim&lt;/code&gt; — splits the commit window into diff + message panes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lewis6991/gitsigns.nvim&lt;/code&gt; — git diff signs in the gutter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;goolord/alpha-nvim&lt;/code&gt; — ASCII &lt;code&gt;NEOVIM&lt;/code&gt; banner dashboard with New File, File Browser, and Quit shortcuts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Options set in one compact idiomatic block: line numbers, cursorline, 2-space tabs, smart case search, &lt;code&gt;clipboard = "unnamedplus"&lt;/code&gt;, persistent undo, no swapfile, trailing space and tab indicators.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;gitcommit&lt;/code&gt; FileType autocmd enables &lt;code&gt;spell&lt;/code&gt; and sets &lt;code&gt;textwidth=72&lt;/code&gt; — matching the 72-char limit the git hook warns about.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Git: GPG Signing + Hooks That Apply Everywhere
&lt;/h2&gt;

&lt;h3&gt;
  
  
  .gitconfig
&lt;/h3&gt;

&lt;p&gt;All commits are GPG-signed by default. &lt;code&gt;core.hooksPath = ~/.git-hooks&lt;/code&gt; redirects hooks globally — every repository on the machine gets these hooks automatically without any per-repo setup.&lt;/p&gt;

&lt;p&gt;Useful aliases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git lg         &lt;span class="c"&gt;# color graph log with relative time&lt;/span&gt;
git today      &lt;span class="c"&gt;# commits since midnight with [HH:MM AM/PM] timestamps&lt;/span&gt;
git yesterday  &lt;span class="c"&gt;# yesterday's commits&lt;/span&gt;
git mine       &lt;span class="c"&gt;# your commits only across all branches&lt;/span&gt;
git last       &lt;span class="c"&gt;# full detail: hash, author, date, full message&lt;/span&gt;
git undo       &lt;span class="c"&gt;# soft reset HEAD~1&lt;/span&gt;
git unstage    &lt;span class="c"&gt;# reset HEAD --&lt;/span&gt;
git el         &lt;span class="c"&gt;# dump log to git_history.txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  commit-msg hook
&lt;/h3&gt;

&lt;p&gt;Validates the Conventional Commits spec: &lt;code&gt;type(scope): subject&lt;/code&gt;. Skips merge commits (&lt;code&gt;^Merge&lt;/code&gt;) and revert commits (&lt;code&gt;^Revert&lt;/code&gt;). Valid types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert. Warns (non-blocking) if the subject line exceeds 72 characters.&lt;/p&gt;

&lt;h3&gt;
  
  
  pre-push hook
&lt;/h3&gt;

&lt;p&gt;Sources &lt;code&gt;~/.zsh_secrets&lt;/code&gt; and checks for &lt;code&gt;GIT_PUSH_PASS&lt;/code&gt;. If set, prompts for a passphrase via &lt;code&gt;/dev/tty&lt;/code&gt; with &lt;code&gt;stty -echo&lt;/code&gt; (no terminal echo). Push proceeds only on match. A lightweight push authorization layer without external tooling.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 GitHub CLI: Contribution Analytics in the Terminal
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gh/.config/gh/config.yml&lt;/code&gt; ships a full suite of GraphQL-powered &lt;code&gt;gh&lt;/code&gt; aliases with ANSI color formatting baked into the &lt;code&gt;--jq&lt;/code&gt; expressions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current activity:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh today              &lt;span class="c"&gt;# every commit with [HH:MM] timestamps, all repos&lt;/span&gt;
gh today-summary      &lt;span class="c"&gt;# repo-by-repo breakdown + total count&lt;/span&gt;
gh today-stats        &lt;span class="c"&gt;# commits, PRs, issues, private contributions&lt;/span&gt;
gh this-month-summary &lt;span class="c"&gt;# monthly breakdown via GraphQL (handles 1000+ commits)&lt;/span&gt;
gh this-year-summary  &lt;span class="c"&gt;# year breakdown sorted by repo&lt;/span&gt;
gh this-year-languages &lt;span class="c"&gt;# top 5 languages by bytes committed this year&lt;/span&gt;
gh streak             &lt;span class="c"&gt;# current and longest commit streak&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Historical lookups:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh yesterday           &lt;span class="c"&gt;# prior day commits with timestamps&lt;/span&gt;
gh last-month-summary  &lt;span class="c"&gt;# prior month breakdown&lt;/span&gt;
gh last-year-languages &lt;span class="c"&gt;# top 5 languages in previous year&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Utilities:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh prs   &lt;span class="c"&gt;# your PRs in the current repo (all states)&lt;/span&gt;
gh open  &lt;span class="c"&gt;# open current repo in browser&lt;/span&gt;
gh co    &lt;span class="c"&gt;# interactive PR checkout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All cross-platform — macOS date flags handled separately from Linux via &lt;code&gt;[[ "$OSTYPE" == "darwin"* ]]&lt;/code&gt; checks in the shell snippets.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎨 Starship: A Two-Line Prompt Showing Everything
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;starship.toml&lt;/code&gt; config uses a two-line layout with &lt;code&gt;$fill&lt;/code&gt; for right-alignment. Line 1 (left): hostname (SSH only), directory, language version modules. Line 1 (right): git branch, git status, command duration, time, OS. Line 2: &lt;code&gt;❯&lt;/code&gt; (green on success, red on error).&lt;/p&gt;

&lt;p&gt;Notable details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Directory&lt;/strong&gt; truncated to 1 level (&lt;code&gt;truncation_length = 1&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git status&lt;/strong&gt; shows ahead/behind counts (⇡/⇣), untracked (?), modified (!), staged (+), renamed (»), deleted ( )&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command duration&lt;/strong&gt; shown after just 1ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom VS Code version&lt;/strong&gt; — &lt;code&gt;[custom.vscode]&lt;/code&gt; runs a shell script that finds the installed binary, reads its &lt;code&gt;package.json&lt;/code&gt;, and shows the version inline in the prompt whenever VS Code is available. Works across &lt;code&gt;code&lt;/code&gt;, &lt;code&gt;code-oss&lt;/code&gt;, and &lt;code&gt;code-insiders&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Language icons for Node, Go, Python, Rust, Java, Kotlin, Lua, Dart, Swift, Zig, Deno, Bun, and more — all Nerd Font.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🖱️ Rofi: Dracula App Launcher (Linux)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;rofi/config.rasi&lt;/code&gt; uses the Dracula palette as CSS variables: &lt;code&gt;MonoLisa 13&lt;/code&gt; font, rounded 8px corners, 95% opaque background (&lt;code&gt;#282a36ee&lt;/code&gt;), &lt;code&gt;bd93f9&lt;/code&gt; purple border and selection highlight, &lt;code&gt;MacTahoe-dark&lt;/code&gt; icon theme. 7 items visible, 1 column, no scrollbar.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎵 ytm-player: YouTube Music in the Terminal
&lt;/h2&gt;

&lt;p&gt;High-quality audio, 80% default volume, &lt;code&gt;prefetch_next&lt;/code&gt; enabled, block-style progress bar, album art in UI. MPRIS enabled for Linux media key integration. LastFM and Discord Rich Presence configured but disabled by default — just uncomment to enable.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Full Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scripts/
├── install.sh               # runs lib/* in order
├── setup.sh                 # interactive numbered menu
├── config/wallpapers.url    # remote wallpapers repo URL
├── utils/detect.sh          # OS, pkg manager, sudo detection
└── lib/
    ├── packages.sh          # all tools via apt/brew/pacman
    ├── plugins.sh           # oh-my-zsh, zsh plugins, tpm
    ├── wallpapers.sh        # clones wallpapers repo
    ├── dotfiles.sh          # stow + chmod git hooks
    ├── go_tools.sh          # gopls, goimports, golangci-lint, air,
    │                        # gotests, govulncheck, shfmt, usql, slim
    │                        # (--update flag supported)
    └── python_tools.sh      # httpie, ytm-player via uv
                             # (--update flag supported)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;usql&lt;/code&gt; is installed with custom build tags (&lt;code&gt;mysql postgres sqlite3 moderncsqlite&lt;/code&gt;) — one universal SQL client for four databases. Both &lt;code&gt;go_tools.sh&lt;/code&gt; and &lt;code&gt;python_tools.sh&lt;/code&gt; call &lt;code&gt;go clean -modcache&lt;/code&gt; or equivalent cleanup after installation.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ CI/CD: Dotfiles That Are Actually Tested
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;shell-validation.yml&lt;/code&gt;&lt;/strong&gt; — Runs &lt;code&gt;shellcheck&lt;/code&gt; on every &lt;code&gt;.sh&lt;/code&gt; file in &lt;code&gt;scripts/&lt;/code&gt; to catch undefined variables, unsafe patterns, and portability issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;scripts-functionality.yml&lt;/code&gt;&lt;/strong&gt; — Integration tests that run the core install scripts end-to-end in a CI environment.&lt;/p&gt;

&lt;p&gt;Full GitHub issue template system: bug reports, feature requests, and config update requests — each with structured fields. PR template with a checklist.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Secret Templates
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docs/templates/.zsh_secrets.template&lt;/code&gt; — Documents exactly which variables to set (including &lt;code&gt;GIT_PUSH_PASS&lt;/code&gt;) in &lt;code&gt;~/.zsh_secrets&lt;/code&gt;, sourced by the pre-push hook.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docs/templates/.connections.usql.template&lt;/code&gt; — Ready-to-fill database connection string template for usql.&lt;/p&gt;




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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Full auto-bootstrap&lt;/span&gt;
git clone https://github.com/GourangaDasSamrat/dotfiles.git ~/dotfiles
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/dotfiles/scripts &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./install.sh

&lt;span class="c"&gt;# Interactive — pick exactly what you want&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/dotfiles/scripts &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./setup.sh

&lt;span class="c"&gt;# Just Go tools&lt;/span&gt;
bash ~/dotfiles/scripts/lib/go_tools.sh

&lt;span class="c"&gt;# Update all Go tools&lt;/span&gt;
bash ~/dotfiles/scripts/lib/go_tools.sh &lt;span class="nt"&gt;--update&lt;/span&gt;

&lt;span class="c"&gt;# Just Python tools&lt;/span&gt;
bash ~/dotfiles/scripts/lib/python_tools.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why This Is Different From Most Dotfiles Repos
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Conditional loading everywhere.&lt;/strong&gt; Nothing breaks if a dependency isn't installed. Every alias, function, and plugin checks for its binary before defining itself. Works on a minimal server and a fully loaded workstation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The functions are genuinely useful replacements.&lt;/strong&gt; &lt;code&gt;apireq&lt;/code&gt; isn't a thin curl wrapper — it's a workflow with saved state. &lt;code&gt;timer&lt;/code&gt; isn't a &lt;code&gt;sleep&lt;/code&gt; alias — it's a full TUI. &lt;code&gt;chpwd&lt;/code&gt; hooks aren't novelties — they save real keystrokes every day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git hygiene enforced at the machine level.&lt;/strong&gt; &lt;code&gt;core.hooksPath&lt;/code&gt; in &lt;code&gt;.gitconfig&lt;/code&gt; points to a global location. Every repository you clone or create automatically gets conventional commit validation and push authorization — not just repos where you remembered to install hooks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modular by design.&lt;/strong&gt; You can take exactly one piece — the fzf config, the git aliases, the &lt;code&gt;apireq&lt;/code&gt; function, the starship prompt — and drop it into your own setup without the rest.&lt;/p&gt;




&lt;p&gt;The repo is at &lt;strong&gt;&lt;a href="https://github.com/GourangaDasSamrat/dotfiles" rel="noopener noreferrer"&gt;github.com/GourangaDasSamrat/dotfiles&lt;/a&gt;&lt;/strong&gt;. Everything described here is real, working code — read the source.&lt;/p&gt;

&lt;p&gt;If it made your terminal feel like home — drop a ⭐&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://github.com/GourangaDasSamrat" rel="noopener noreferrer"&gt;Gouranga Das Samrat&lt;/a&gt; · MIT License · Issues and PRs welcome&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>architecture</category>
    </item>
    <item>
      <title>🚀 Handling Multiple Form Submissions Gracefully on Frontend</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 26 Apr 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/handling-multiple-form-submissions-gracefully-on-frontend-2kfo</link>
      <guid>https://dev.to/gouranga-das-khulna/handling-multiple-form-submissions-gracefully-on-frontend-2kfo</guid>
      <description>&lt;h2&gt;
  
  
  How to Build a User-Proof, Scalable, and Clean Form Submission Flow
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Handling multiple form submissions is one of those subtle — but critical — frontend challenges every engineer encounters. Users double-click buttons, spam taps, refresh pages, or simply get impatient. And if your backend isn’t fully idempotent, this can quickly turn into:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Duplicate entries&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Failed or partial saves&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Data corruption&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Frustrated users&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;A small UX issue suddenly becomes a large engineering headache.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In this article, let’s break down&lt;/em&gt; &lt;strong&gt;&lt;em&gt;a reliable, scalable strategy to gracefully handle multiple submissions on the frontend&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔹 1. Disable the Submit Button After the First Click
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The simplest and most effective safeguard.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Once the user clicks&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Submit&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, immediately:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Disable the button&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Show a loader or progress indicator&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This prevents accidental double-clicks and gives the user a visual cue that the action is in progress.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔹 2. Use Debouncing or Throttling
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Some submissions get triggered by event-based actions, like&lt;/em&gt; &lt;code&gt;_onChange_&lt;/code&gt;&lt;em&gt;,&lt;/em&gt; &lt;code&gt;_onEnter_&lt;/code&gt;&lt;em&gt;, or UI interactions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To prevent rapid re-triggers:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;Debouncing&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;delays execution until the user stops triggering the event.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;em&gt;Throttling&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;ensures the event fires only once in a fixed interval.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This protects your API from spammy or repeated calls.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔹 3. Implement a Client-Side Request Queue
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;When multiple submissions are possible due to network delays or user impatience, a&lt;/em&gt; &lt;strong&gt;&lt;em&gt;frontend queue&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;ensures requests are processed&lt;/em&gt; &lt;strong&gt;&lt;em&gt;sequentially&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, not all at once.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Richa Gautam 🌷’s stories in your inbox
&lt;/h2&gt;

&lt;p&gt;Join Medium for free to get updates from this writer.&lt;/p&gt;

&lt;p&gt;Subscribe&lt;/p&gt;

&lt;p&gt;Subscribe&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This guarantees:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Predictable behavior&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Controlled request flow&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Preventing race conditions or overwrites&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔹 4. Use Idempotency Keys (Best Practice)
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is the gold standard — especially in payments, forms, and transactional flows.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Generate a&lt;/em&gt; &lt;strong&gt;&lt;em&gt;unique key (UUID)&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;for every submission request.&lt;br&gt;
Send it to the backend with the payload.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If the user accidentally sends the same request 10 times:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;➡️ The backend will treat all duplicates as a single operation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This ensures&lt;/em&gt; &lt;strong&gt;&lt;em&gt;data integrity&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, even if the user hammers the button.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔹 5. Implement Optimistic UI Updates
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Users hate waiting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To improve perceived performance:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Update the UI instantly&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Assume the operation will succeed&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Roll back changes only if the request fails&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This creates a smooth, responsive experience while maintaining correctness.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Final Thoughts: Small UX Patterns Have Big Impact
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;When your app scales, even tiny interactions — like form submission behavior — start to matter.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A robust submission strategy:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Improves data integrity&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Reduces accidental duplicates&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Makes your UI feel polished and responsive&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Builds user confidence and trust&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Even if a user clicks 10 times, your system stays stable and your data stays clean.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🙏 Stay Connected!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;🔔 Follow for more guides on JavaScript, React.js &amp;amp; interview prep.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;**_Thankyou! for reading my article.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>7 Secrets Your Framework Docs Don’t Tell You About Standalone Components</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 19 Apr 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/7-secrets-your-framework-docs-dont-tell-you-about-standalone-components-2920</link>
      <guid>https://dev.to/gouranga-das-khulna/7-secrets-your-framework-docs-dont-tell-you-about-standalone-components-2920</guid>
      <description>&lt;p&gt;You’ve probably heard about Angular’s standalone components — they’re a fresh way to build apps without relying on NgModules. But there’s more to them than just skipping modules. Standalone components let you create self-contained building blocks that you import exactly where you need them, which makes your app cleaner and easier to manage. They simplify how you organize your code and open up new possibilities for building faster, more modular apps.&lt;/p&gt;

&lt;p&gt;This article isn’t about the basics you’ve heard before. Instead, it dives into seven hidden tips and real-world advantages that most people overlook. Whether you’re new to Angular or a seasoned developer, these insights will help you get more from standalone components. Even if you’re a manager or stakeholder curious about how Angular’s latest features can impact your projects, this guide will give you useful, practical knowledge to make development smoother and more efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret 1: Standalone Components Simplify Dependency Management
&lt;/h2&gt;

&lt;p&gt;Standalone components in Angular simplify dependency management by letting each component handle its own imports right inside its decorator. This eliminates the need for bulky NgModule declarations and cuts out a lot of repetitive boilerplate code. Basically, your component says, “Here’s exactly what I need,” making dependencies clearer and more local.&lt;/p&gt;

&lt;p&gt;This approach also makes teamwork smoother. When dependencies are tied to the component itself, it’s easier for developers to understand and manage their parts without digging through large module files. It reduces conflicts, speeds up onboarding, and encourages building reusable, self-contained components.&lt;/p&gt;

&lt;p&gt;For example, instead of declaring a component and its imports in an NgModule like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@NgModule({
  declarations: [OldComponent],
  imports: [CommonModule, FormsModule, SharedModule],
})
export class AppModule { }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You convert it to a standalone component that imports what it needs directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component({
  selector: 'app-new',
  standalone: true,
  imports: [CommonModule, FormsModule, SharedModule],
  templateUrl: './new.component.html',
})
export class NewComponent { }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more module clutter, just a clear, self-sufficient component. This not only makes your code easier to manage but also sets you up for better lazy loading and performance optimization. Overall, standalone components cut down complexity, boost collaboration, and keep your Angular apps clean and scalable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret 2: Lazy Loading Made Easy with Standalone Components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why It Matters
&lt;/h3&gt;

&lt;p&gt;Lazy loading helps your app start faster by loading only what’s needed when it’s needed. Angular’s standalone components make lazy loading even simpler — no more wrapping components inside modules just to load them on demand. With the &lt;code&gt;loadComponent&lt;/code&gt; API, you load standalone components directly, which trims down your code and speeds up your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Old vs. New Lazy Loading
&lt;/h3&gt;

&lt;p&gt;Before, you had to create entire NgModules to lazy load parts of your app, which added extra setup and larger bundles. Now, you can lazy load standalone components directly, skipping that module overhead entirely. It’s like ordering a single item instead of the whole combo — more precise and less bulky.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Boosts
&lt;/h3&gt;

&lt;p&gt;Loading only the components you need means smaller initial downloads and faster startup times. Angular can also optimize your app better since there’s no extra module wrapping. The result? A nimbler app that feels faster and more responsive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips for Organizing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Use &lt;code&gt;loadComponent&lt;/code&gt; in your routes to lazy load standalone components.&lt;/li&gt;
&lt;li&gt;  Group related components but avoid forcing modules just for lazy loading.&lt;/li&gt;
&lt;li&gt;  Don’t import lazy components eagerly elsewhere; keep them truly lazy.&lt;/li&gt;
&lt;li&gt;  Provide services inside standalone components for localized scope.&lt;/li&gt;
&lt;/ul&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const routes = [  {
    path: 'dashboard',
    loadComponent: () =&amp;gt; import('./dashboard.component').then(m =&amp;gt; m.DashboardComponent)
  },
  {
    path: 'profile',
    loadComponent: () =&amp;gt; import('./profile.component').then(m =&amp;gt; m.ProfileComponent)
  }
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this setup, Angular loads each standalone component only when its route is visited. Simple, clean, and fast!&lt;/p&gt;

&lt;p&gt;In short, standalone components make lazy loading straightforward and more efficient, helping you build faster Angular apps with less hassle. Give it a try — you’ll love the boost in speed and simplicity!&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret 3: Standalone Components Make Your Angular Apps Smaller and Faster
&lt;/h2&gt;

&lt;p&gt;One of the best things about Angular’s standalone components is how they help your app load quicker and run smoother by making the bundles smaller. This happens thanks to better build optimization and tree shaking — which just means cutting out unused code automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smaller Bundle Sizes Thanks to Modular Dependencies
&lt;/h3&gt;

&lt;p&gt;With standalone components, each piece knows exactly what it needs, instead of hiding behind big NgModules that pack everything together. This modular setup means only the parts you actually use get included, making your final app bundle much lighter and faster to download.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Tree Shaking Compared to NgModules
&lt;/h3&gt;

&lt;p&gt;Tree shaking is like cleaning out your closet — it removes the stuff you don’t wear (or use). Traditional NgModules can be a bit messy because they bring in whole modules even if you only need part of them. Standalone components are neat and precise, so tools can trim your code more effectively, resulting in less unnecessary code in your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Use This for Speedier Apps
&lt;/h3&gt;

&lt;p&gt;To get the most out of standalone components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Switch your key components to standalone gradually.&lt;/li&gt;
&lt;li&gt;  Only import what each component really needs.&lt;/li&gt;
&lt;li&gt;  Use lazy loading with standalone components to load parts only when needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following these steps helps your app start faster and feel more responsive, especially for users with slower devices or connections.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Example: Smaller and Faster Bundles
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhs0fkvcbbirkqzmrs3s7.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%2Fhs0fkvcbbirkqzmrs3s7.png" alt="captionless image" width="742" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, adopting standalone components can shrink your bundle by over 35% and speed up load times significantly.&lt;/p&gt;

&lt;p&gt;Standalone components give you control and freedom to keep your Angular apps lean and fast, making everyone’s life easier — from developers to end users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret 4: Easier Migration Path — The Hybrid Approach
&lt;/h2&gt;

&lt;p&gt;Migrating a big Angular app doesn’t have to mean a risky, all‑at‑once rewrite. Angular’s hybrid approach lets you mix standalone components and NgModules, so you can modernize piece by piece without breaking anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Hybrid Works for Big Apps
&lt;/h3&gt;

&lt;p&gt;Large apps need stability and flexibility. With hybrid migration, you keep NgModules running while gradually introducing standalone components. This means you can keep shipping new features, avoid long freezes, and reduce risk. If something goes wrong, you can roll back without taking the whole app offline.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Migrate Step by Step
&lt;/h3&gt;

&lt;p&gt;Start by picking a small, self‑contained area — like a feature or a route — and convert it to standalone components. Use Angular’s migration tools to help automate the process. Move your routing one route at a time, test after each change, and deploy small updates. Once a section is fully migrated, clean up the old module wiring before moving on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Pitfalls to Avoid
&lt;/h3&gt;

&lt;p&gt;Don’t try to migrate everything at once — it’s tempting, but it usually leads to delays and bugs. Avoid leaving temporary fixes in place, as they can turn into technical debt. Watch out for tangled dependencies and shared state, which can make migration messy. Untangle things as you go.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Quick Example
&lt;/h3&gt;

&lt;p&gt;Imagine a banking dashboard. Start by migrating the notifications section to standalone components while leaving the main dashboard as is. Move the reports section route by route, validating with tests and real traffic. Keep stakeholders updated with simple metrics like “40% of routes now standalone.” Once everything is migrated, remove the old modules and glue code, leaving behind a cleaner, faster Angular app.&lt;/p&gt;

&lt;p&gt;The hybrid approach lets you modernize with control — no big bang, no drama, just steady progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret 5: Standalone Components Improve Testing Isolation
&lt;/h2&gt;

&lt;p&gt;Standalone components in Angular make unit testing simpler and more focused. They help you write cleaner, better isolated tests that are easier to maintain and quicker to run.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Standalone Components Change Test Setup
&lt;/h3&gt;

&lt;p&gt;With traditional components, tests require setting up a testing module where you declare the component and import all necessary modules. This can get bulky and hard to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Karol Modelski’s stories in your inbox
&lt;/h2&gt;

&lt;p&gt;Join Medium for free to get updates from this writer.&lt;/p&gt;

&lt;p&gt;Subscribe&lt;/p&gt;

&lt;p&gt;Subscribe&lt;/p&gt;

&lt;p&gt;Standalone components handle their own dependencies inside their definition, so in tests you just import the component directly. This makes the setup shorter and much less cluttered, letting you focus on testing instead of configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Makes Tests Easier to Maintain
&lt;/h3&gt;

&lt;p&gt;Since each standalone component controls its own dependencies, test setups update automatically when the component changes. Your tests stay stable even if the rest of the app’s module structure changes.&lt;/p&gt;

&lt;p&gt;This means less risk of broken tests from module tweaks and easier refactoring overall. Simpler test setups also makes tests clearer and less intimidating for the whole team.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Speeds Up Test Execution
&lt;/h3&gt;

&lt;p&gt;Skipping heavy module setups means tests compile and run faster. The isolation standalone components bring also helps test runners parallelize and cache tests better, giving you faster feedback when coding or in CI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: A Clean Unit Test for a Standalone Component
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyStandaloneComponent } from './my-standalone.component';
describe('MyStandaloneComponent', () =&amp;gt; {
  let fixture: ComponentFixture&amp;lt;MyStandaloneComponent&amp;gt;;
  let component: MyStandaloneComponent;
  beforeEach(async () =&amp;gt; {
    await TestBed.configureTestingModule({
      imports: [MyStandaloneComponent]  // Just import directly
    }).compileComponents();
    fixture = TestBed.createComponent(MyStandaloneComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
  it('should create the component', () =&amp;gt; {
    expect(component).toBeTruthy();
  });
  it('should have the correct default title', () =&amp;gt; {
    expect(component.title).toBe('Hello Standalone');
  });
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No declarations or extra module imports needed — just the component. This makes tests clean and isolated.&lt;/p&gt;

&lt;p&gt;Standalone components help you build faster, more maintainable test suites by simplifying setup, improving isolation, and speeding up execution. They make testing in Angular a smoother and more enjoyable experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret 6: Standalone Components Make Reuse a Breeze
&lt;/h2&gt;

&lt;p&gt;Standalone components in Angular let you build pieces of your app like LEGO bricks — snap them together without the module fuss. Now, components just import each other directly, so building and updating your UI is smoother and less confusing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mix and Match, No Headaches
&lt;/h3&gt;

&lt;p&gt;Want one reusable component to use another? Just import it. There’s no more juggling NgModules — these components stand on their own. It’s all about working smarter and keeping things simple.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perfect for Design Systems
&lt;/h3&gt;

&lt;p&gt;Design systems thrive on reusable, consistent parts. Standalone components keep logic and styles self-contained, so sharing a slick button or form input across different projects is painless. This keeps every app on-brand and makes updates quick.&lt;/p&gt;

&lt;h3&gt;
  
  
  Large Teams: Speed and Consistency
&lt;/h3&gt;

&lt;p&gt;When teams are big, code duplication can be a nightmare. With standalone components, anyone can grab shared widgets and use them, which means less confusion and more teamwork. Updates get rolled out fast and everyone stays in sync.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Example: The Trusty Button
&lt;/h3&gt;

&lt;p&gt;Picture one button component that looks and works great. Build it once as a standalone. Need it elsewhere? Just pull it in — no extra config, no module drama. That’s a win for everyone.&lt;/p&gt;

&lt;p&gt;Standalone components keep your code neat, easy to reuse, and a joy for both small teams and big enterprises. Once you try them, you’ll wonder how you ever lived without them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret 7: Advanced Providers and Dependency Injection Tricks
&lt;/h2&gt;

&lt;p&gt;Angular’s dependency injection (DI) system gets even more powerful with standalone components. Here’s how to manage your services smartly without the usual complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local vs Global Providers
&lt;/h3&gt;

&lt;p&gt;You can provide services globally (available everywhere) or locally (only inside a specific standalone component and its children). Global services act like shared singletons for the whole app. Local services are new instances each time the component loads, keeping state or behavior isolated.&lt;/p&gt;

&lt;p&gt;Use local providers when you need independent service instances that won’t interfere with other parts of your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Scopes in Standalone Components
&lt;/h3&gt;

&lt;p&gt;Standalone components let you control exactly where services live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Adding services directly in a standalone component’s &lt;code&gt;providers&lt;/code&gt; means those services are scoped to that component and its subtree.&lt;/li&gt;
&lt;li&gt;  This allows you to run multiple instances of the same service in different component trees.&lt;/li&gt;
&lt;li&gt;  You can also override global providers locally when needed, for example, to swap a real service with a mock during testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Hierarchical Injectors and Standalone Components
&lt;/h3&gt;

&lt;p&gt;Angular’s DI is hierarchical. The root injector is global, but standalone components can add their own injectors by declaring providers locally. Child components inherit from these injectors unless they declare their own providers.&lt;/p&gt;

&lt;p&gt;This makes it easy to share some services globally while having specialized versions in particular sections of your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Different Service Scopes in Action
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Injectable({ providedIn: 'root' })
export class GlobalService { 
  getValue(): string {
    return 'Global service value';
  } 
}
@Injectable()
export class LocalService { 
  getValue(): string {
    return 'Local service value';
  } 
}
@Component({
  selector: 'app-standalone',
  standalone: true,
  template: `
    &amp;lt;p&amp;gt;{{globalValue}}&amp;lt;/p&amp;gt;
    &amp;lt;p&amp;gt;{{localValue}}&amp;lt;/p&amp;gt;
    &amp;lt;app-child&amp;gt;&amp;lt;/app-child&amp;gt;
  `,
  providers: [LocalService],
})
export class StandaloneComponent {
  private globalService = inject(GlobalService);
  private localService = inject(LocalService);
  protected globalValue = this.globalService.getValue();
  protected localValue = this.localService.getValue();
}
@Component({
  selector: 'app-child',
  standalone: true,
  template: `&amp;lt;p&amp;gt;Child uses local: {{ localValue }}&amp;lt;/p&amp;gt;`,
})
export class ChildComponent {
  private localService = inject(LocalService);
  protected localValue = this.localService.getValue();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;GlobalService&lt;/code&gt; is shared app-wide. The &lt;code&gt;LocalService&lt;/code&gt; is created fresh for &lt;code&gt;StandaloneComponent&lt;/code&gt; and passed down to its child, giving you neat control over service lifetimes and visibility.&lt;/p&gt;

&lt;p&gt;This approach keeps your Angular app modular and lean, with services existing only where they’re needed. It’s a simple but powerful way to master dependency injection in standalone components.​&lt;/p&gt;

&lt;h2&gt;
  
  
  To sum it all up
&lt;/h2&gt;

&lt;p&gt;You’ve learned 7 key secrets that make Angular apps simpler, faster, and easier to work with. Using standalone components as the default helps keep features self-contained and avoids the old tangled NgModule mess. Smarter routing and feature boundaries make your app easier to understand and faster to load. Lean state management and change detection patterns keep your UI smooth and responsive. All these add up to a happier, more productive team and better apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to do next
&lt;/h3&gt;

&lt;p&gt;Don’t try to change everything at once. Pick one secret and test it out in a small part of your app. Maybe create a standalone component, lazy-load a route, or optimize change detection on a slow screen. Measure the impact, then decide if it’s worth applying more broadly. If you lead a team, make it a small sprint goal, so everyone can learn and improve together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Want to dive deeper?
&lt;/h3&gt;

&lt;p&gt;Start with the official Angular docs — they have great guides on standalone components, performance, and architecture. When you’re ready, check out expert blogs, tutorials, and community resources to see how others solve real-world problems. Join Angular meetups, workshops, or conferences to stay up to date and learn from the best.&lt;/p&gt;

&lt;p&gt;Keep experimenting, and watch your Angular apps and teams thrive.&lt;/p&gt;

&lt;p&gt;Your support helps me create more practical guides and tools tailored for the frontend and startup community.&lt;/p&gt;

&lt;p&gt;Let’s keep building together 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>angular</category>
      <category>programming</category>
    </item>
    <item>
      <title>How To Migrate to Signal Inputs and Queries Without Rewriting Your Templates</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 12 Apr 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/how-to-migrate-to-signal-inputs-and-queries-without-rewriting-your-templates-3cf6</link>
      <guid>https://dev.to/gouranga-das-khulna/how-to-migrate-to-signal-inputs-and-queries-without-rewriting-your-templates-3cf6</guid>
      <description>&lt;p&gt;Hey, let’s talk about why reactive programming — and especially Angular’s signals — are blowing up right now. You’ve probably noticed how apps need to feel snappier and more responsive these days, right? Signals make that happen by letting your Angular code react to data changes automatically, cutting out a ton of the old-school hassle with change detection.&lt;/p&gt;

&lt;p&gt;So, quick rundown: Signal inputs are like smart inputs that feed reactive data straight into your components, and signal queries let you pull and react to derived stuff from those inputs. They’re a big deal because they make your apps predictably fast and way easier to manage — no more wrestling with endless subscriptions or zone.js quirks.&lt;/p&gt;

&lt;p&gt;If you’re an Angular dev or tech lead itching to modernize without ripping apart your templates, you’re in the right spot. We’ll dive into migration tricks that keep your existing views intact, so you can upgrade efficiently and get those wins without the headache.​&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Signal Inputs and Queries in Angular
&lt;/h2&gt;

&lt;p&gt;You ever get tired of Angular’s old-school data passing feeling like a chore? Yeah, me too. That’s where signal inputs and queries come in — they’re the new, smooth way to handle inputs and grab child elements, all with built-in reactivity that keeps things zippy. No matter if you’re coding all day or just overseeing the team, this stuff makes apps faster and way less buggy. Let’s dive in and see why everyone’s switching over.​&lt;/p&gt;

&lt;h3&gt;
  
  
  What Are Signal Inputs and Queries?
&lt;/h3&gt;

&lt;p&gt;Hey, let’s talk about signal inputs and queries in Angular — they’re game-changers for passing data around and grabbing references to stuff in your components. Signal inputs use the &lt;code&gt;input()&lt;/code&gt; function instead of the old &lt;code&gt;@Input()&lt;/code&gt; decorator, giving you a reactive value that updates automatically when the parent changes it. And queries? Think &lt;code&gt;viewChild()&lt;/code&gt; or &lt;code&gt;contentChild()&lt;/code&gt;—they replace &lt;code&gt;@ViewChild&lt;/code&gt; and &lt;code&gt;@ContentChild&lt;/code&gt;, handing you back a signal that stays fresh without all the lifecycle hook hassle.​&lt;/p&gt;

&lt;p&gt;You know how traditional inputs meant hooking into &lt;code&gt;ngOnChanges&lt;/code&gt; and dealing with Zone.js firing off change detection everywhere? Signals fix that mess. They make state super reactive, so only the parts that need updating actually do—pair them with &lt;code&gt;computed()&lt;/code&gt; or &lt;code&gt;effect()&lt;/code&gt;, and your app feels snappier, especially as it grows. No more guessing when things update; it's all predictable and fine-grained.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Why They’re a Big Upgrade
&lt;/h3&gt;

&lt;p&gt;Picture this: old-school inputs could trigger full tree scans for changes, slowing things down. Signals? They mark OnPush components dirty only when needed, ditch &lt;code&gt;ngOnChanges&lt;/code&gt;, and work zoneless for even better speed. Queries give you live signals instead of static lists, so you access kids reactively—no subscriptions or manual checks required. The perks hit hard: less code, easier debugging, and performance that scales, which managers love for real-world apps.​&lt;/p&gt;

&lt;p&gt;Plus, you’ve got handy options like &lt;code&gt;required&lt;/code&gt;, &lt;code&gt;alias&lt;/code&gt;, or &lt;code&gt;transform&lt;/code&gt; right in the API. It cuts boilerplate and makes your components cleaner. Stakeholders get why this matters—fewer bugs, faster UIs, and dev teams move quicker.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Seeing Them in Action
&lt;/h3&gt;

&lt;p&gt;Want to see it? Here’s a quick child component grabbing a count from its parent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, input, computed } from '@angular/core';
@Component({
  selector: 'app-counter',
  template: `&amp;lt;p&amp;gt;Count: {{ doubledCount() }}&amp;lt;/p&amp;gt;`
})
export class CounterComponent {
  count = input.required&amp;lt;number&amp;gt;();
  doubledCount = computed(() =&amp;gt; this.count() * 2);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just bind it like &lt;code&gt;&amp;lt;app-counter [count]="parentCount"&amp;gt;&amp;lt;/app-counter&amp;gt;&lt;/code&gt;. Boom—changes flow instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Karol Modelski’s stories in your inbox
&lt;/h2&gt;

&lt;p&gt;Join Medium for free to get updates from this writer.&lt;/p&gt;

&lt;p&gt;Subscribe&lt;/p&gt;

&lt;p&gt;Subscribe&lt;/p&gt;

&lt;p&gt;For queries, say you need an input field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Component, viewChild, ElementRef } from '@angular/core';
@Component({
  selector: 'app-search',
  template: `&amp;lt;input #searchInput /&amp;gt;`
})
export class SearchComponent {
  searchInput = viewChild.required&amp;lt;ElementRef&amp;lt;HTMLInputElement&amp;gt;&amp;gt;('searchInput');
  focusSearch() {
    this.searchInput().nativeElement.focus();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Content queries work the same for projected kids. Simple, right? Less fuss, more power — you’ll wonder how you lived without ‘em.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration Strategies Without Template Rewrites
&lt;/h2&gt;

&lt;p&gt;Look, migrating your old Angular templates to signals doesn’t have to mean ripping everything apart and starting over. Signals make your app snappier, easier to manage, and way more reactive — perfect for keeping things modern without the chaos. In this chapter, we’ll dive into straightforward strategies that let you wrap, adapt, and mix signals into your legacy code with barely a template tweak. Stick around for practical steps and a real dialog example that shows it all in action.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Migrating Legacy Templates to Signals is Tricky
&lt;/h3&gt;

&lt;p&gt;Hey, let’s talk about the real headaches when you’re trying to shift old Angular templates over to signals. The big issue? Signals need that &lt;code&gt;()&lt;/code&gt; to read them—like &lt;code&gt;count()&lt;/code&gt;—but your legacy templates just use plain properties without it. Messing with templates directly can break everything in a huge app, spark a testing nightmare, and even tank production if your inputs get mutated weirdly or tie into &lt;code&gt;ngOnChanges&lt;/code&gt;. That's why smart folks focus on tweaking the TypeScript side first, leaving your HTML alone.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach 1: Wrap Inputs and Queries in Signals
&lt;/h3&gt;

&lt;p&gt;Start simple: wrap your old &lt;code&gt;@Input&lt;/code&gt;s and &lt;code&gt;@Output&lt;/code&gt;s, plus those &lt;code&gt;ViewChild&lt;/code&gt; queries, right into signals—without touching the templates at all. Fire up Angular's schematics with &lt;code&gt;ng generate @angular/core:signal-input-migration&lt;/code&gt;, and it'll swap safe inputs to &lt;code&gt;input()&lt;/code&gt; signals automatically. It flags risky mutable ones with TODOs if you add &lt;code&gt;--insert-todos&lt;/code&gt;. For queries, grab &lt;code&gt;ng generate @angular/core:signal-queries-migration --best-effort-mode&lt;/code&gt; to link &lt;code&gt;@ViewChild&lt;/code&gt; to &lt;code&gt;viewChild()&lt;/code&gt;, and boom—your templates keep binding like nothing changed.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach 2: Adapters and Helpers to the Rescue
&lt;/h3&gt;

&lt;p&gt;Don’t want to invoke signals everywhere? Whip up quick adapters or getters to make them act like regular properties. Something like &lt;code&gt;get openState() { return this.openSignal(); }&lt;/code&gt; lets your template use &lt;code&gt;[open]="openState"&lt;/code&gt; no sweat. Or lean on &lt;code&gt;@angular/core/rxjs-interop&lt;/code&gt; with &lt;code&gt;toSignal&lt;/code&gt; for observables—&lt;code&gt;legacyData = toSignal(this.observableData$)&lt;/code&gt;—ditching the &lt;code&gt;async&lt;/code&gt; pipe. Helpers like &lt;code&gt;linkedSignal&lt;/code&gt; can even compute derived stuff reactively on the fly.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach 3: Go Incremental and Hybrid
&lt;/h3&gt;

&lt;p&gt;Nobody migrates a whole app overnight, right? Mix signals with your legacy code piece by piece — maybe one module via &lt;code&gt;ng generate @angular/core:signal-input-migration --path=src/app/feature&lt;/code&gt;. New kid components get signals, parents stay legacy, and Angular's fine-grained tracking keeps things zippy without zoneless drama. Slice it up, test as you go, and use VS Code refactors for &lt;code&gt;@Input&lt;/code&gt; to &lt;code&gt;input()&lt;/code&gt; swaps plus &lt;code&gt;effect()&lt;/code&gt; for side effects. Stability first!​&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Example: A Simple Dialog Toggle
&lt;/h3&gt;

&lt;p&gt;Picture this: you’ve got a legacy dialog with &lt;code&gt;@Input() open: boolean;&lt;/code&gt; and a parent template like &lt;code&gt;&amp;lt;app-dialog [open]="isOpen"&amp;gt;&lt;/code&gt;, toggling via &lt;code&gt;this.isOpen = !this.isOpen&lt;/code&gt;. Migrate by adding &lt;code&gt;isOpen = signal(false);&lt;/code&gt; and that getter &lt;code&gt;get isOpenState() { return this.isOpen(); }&lt;/code&gt;, then toggle with &lt;code&gt;this.isOpen.update(v =&amp;gt; !v)&lt;/code&gt;. Template? Untouched. Add &lt;code&gt;effect(() =&amp;gt; console.log('Dialog:', this.isOpen()))&lt;/code&gt; for fun, and schematics handle most of it—your app's now signal-powered with zero HTML fuss.​&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices and Tooling Support
&lt;/h2&gt;

&lt;p&gt;Hey, migrating to Angular Signals doesn’t have to be a headache. You can lean on Angular’s built-in schematics to handle the basics — like swapping inputs and queries — then tweak the tricky bits yourself. This way, you snag those sweet performance boosts from smarter change detection without wrecking your legacy code.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart Patterns to Follow
&lt;/h3&gt;

&lt;p&gt;Look, start small: tackle simple inputs and queries first with the automated tools. For anything fancier, like RxJS streams or nested data, go manual and keep things immutable — tools like Immer make that a breeze by letting you “mutate” safely.​&lt;br&gt;
Don’t write directly to signal inputs (it’ll bite you), and use &lt;code&gt;toObservable()&lt;/code&gt; to bridge signals back to RxJS when needed. Oh, and always chase down those schematic TODOs right away—they're your roadmap to pitfalls avoided.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools That Make It Easy
&lt;/h3&gt;

&lt;p&gt;Angular’s CLI has your back with schematics that do the grunt work. Fire up &lt;code&gt;ng generate @angular/core:signal-input-migration --best-effort-mode&lt;/code&gt; to flip &lt;code&gt;@Input()&lt;/code&gt; to &lt;code&gt;input()&lt;/code&gt;, and it'll flag anything sketchy with TODOs.​&lt;br&gt;
Same for outputs (&lt;code&gt;signal-output-migration&lt;/code&gt;) and queries (&lt;code&gt;signal-queries-migration&lt;/code&gt;—use &lt;code&gt;--path&lt;/code&gt; to target folders).​&lt;br&gt;
Stuff like ngxtension helps keep your input names intact too. No more copy-paste nightmares.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing It Right
&lt;/h3&gt;

&lt;p&gt;You gotta test like your app depends on it — which it does. Mock signals in unit tests with &lt;code&gt;toSignal()&lt;/code&gt; for observables, then fire up Angular DevTools to eyeball those change detection wins (fewer cycles, happier users).​&lt;br&gt;
Run your full e2e suite after, hunt schematic reports for weirdness, and manually poke the TODO cases. Right? Performance graphs don't lie.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; Bump to Angular 19+: &lt;code&gt;ng update @angular/cli @angular/core&lt;/code&gt;. Easy start.&lt;/li&gt;
&lt;li&gt; Hit the schematics in order: inputs, outputs, queries. Safety flags on.&lt;/li&gt;
&lt;li&gt; Hunt TODOs, swap RxJS where it fits.&lt;/li&gt;
&lt;li&gt; Test hard — units, perf, e2e.&lt;/li&gt;
&lt;li&gt; Roll out bit by bit, watch prod for zoneless vibes if you’re going there.​&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Using Signal inputs and queries in your Angular apps is a smart move. They make your app faster and easier to maintain by letting you react smoothly to changes in data. This approach helps your app feel more responsive, which improves the user experience.&lt;/p&gt;

&lt;p&gt;You don’t have to switch everything all at once. Try adding Signals little by little in parts of your app that need the most attention. This way, you avoid big rewrites and can see benefits as you go, keeping your project stable and moving forward.&lt;/p&gt;

&lt;p&gt;If you want to learn more, check out Angular’s official docs and tutorials on Signals and reactive programming. There are plenty of guides and articles that break down the concepts and show practical examples to help you get comfortable with this modern Angular style.&lt;/p&gt;

&lt;p&gt;Your support helps me create more practical guides and tools tailored for the frontend and startup community.&lt;/p&gt;

&lt;p&gt;Let’s keep building together 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>angular</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Here’s Exactly How I Implemented @defer for Granular Code Splitting in Days — Step-by-Step</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 05 Apr 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/heres-exactly-how-i-implemented-defer-for-granular-code-splitting-in-days-step-by-step-1ko1</link>
      <guid>https://dev.to/gouranga-das-khulna/heres-exactly-how-i-implemented-defer-for-granular-code-splitting-in-days-step-by-step-1ko1</guid>
      <description>&lt;p&gt;Picture this: you slash your Angular app’s initial bundle by 40% in days, loading those heavy charts only when users scroll down — no routing headaches required. Angular’s &lt;code&gt;@defer&lt;/code&gt; (dropped in v17) is your new best friend for smart, template-level lazy loading of standalone components, directives, and pipes—perfectly teaming up with router lazy loading to crush Core Web Vitals like LCP.​&lt;/p&gt;

&lt;p&gt;Whether you’re a beginner dipping into &lt;code&gt;@defer&lt;/code&gt; magic, an expert tweaking performance, or a stakeholder chasing that ROI from snappier apps, this guide's got you. We'll roll through hands-on steps, code snippets, killer triggers (viewport scrolls, button clicks), placeholder tricks to kill layout jank, and error-handling smarts—skipping compiler deep dives.​&lt;/p&gt;

&lt;p&gt;Ready to prefetch on idle, render on hover, and watch your app fly? Let’s dive in and supercharge your Angular game!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/defer"&gt;@defer&lt;/a&gt; Fundamentals and Setup
&lt;/h2&gt;

&lt;p&gt;Angular’s &lt;code&gt;@defer&lt;/code&gt; block is a game-changer for performance, letting you split heavy template sections—like charts or dashboards—into separate JavaScript bundles that load only when triggered by events such as viewport entry, user interaction, or browser idle time. This slashes your initial payload, speeding up Largest Contentful Paint (LCP) and overall app startup, especially in large single-page apps where not every user needs every feature right away.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements for Success
&lt;/h3&gt;

&lt;p&gt;You’ll need Angular 17 or later, as &lt;code&gt;@defer&lt;/code&gt; leverages the new control flow syntax and stable deferrable views from Angular 18 onward. Components, directives, and pipes inside the &lt;code&gt;@defer&lt;/code&gt; block must be standalone and not referenced elsewhere in the same file—think no sneaky ViewChild queries or imports outside the block, or they'll eagerly load anyway. Transitive dependencies can mix standalone or NgModule-based, but keep placeholders lightweight since their deps load upfront.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Basic Syntax in Action
&lt;/h3&gt;

&lt;p&gt;Kick off with something simple: &lt;code&gt;@defer (on viewport) { &amp;lt;heavy-chart /&amp;gt; } @placeholder { &amp;lt;skeleton-loader /&amp;gt; }&lt;/code&gt;. Here, the chart bundle loads when the placeholder hits the viewport, swapping the skeleton for the real deal—triggers like &lt;code&gt;idle&lt;/code&gt; (default), &lt;code&gt;interaction&lt;/code&gt;, &lt;code&gt;hover&lt;/code&gt;, &lt;code&gt;timer(2s)&lt;/code&gt;, or custom &lt;code&gt;when showLargeChart&lt;/code&gt; give you precise control. Add &lt;code&gt;@loading (minimum 1s)&lt;/code&gt; for spinners during fetch, or &lt;code&gt;@error { Retry? }&lt;/code&gt; for fails, all while prefetching separately via &lt;code&gt;prefetch on idle&lt;/code&gt;.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify Your Build Wins
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;ng build&lt;/code&gt; and scan the CLI output for new chunks like &lt;code&gt;defer-heavy-chart.js&lt;/code&gt;—that's your proof the split happened. Fire up the dev server, hit the Network tab in Chrome DevTools, and watch lazy loads kick in on triggers; no extra bundle until viewport or click, confirming a leaner main payload. Pro tip: Test with &lt;code&gt;TestBed.deferBlockBehavior = DeferBlockBehavior.Manual&lt;/code&gt; for unit tests simulating states.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Starter: Dashboard Magic
&lt;/h3&gt;

&lt;p&gt;Wrap a data-heavy dashboard widget in &lt;code&gt;@defer (on viewport; prefetch on idle) { &amp;lt;analytics-widget /&amp;gt; } @placeholder (minimum 500ms) { &amp;lt;chart-skeleton /&amp;gt; }&lt;/code&gt; and watch your bundle shrink by 30% or more on complex pages—perfect for below-the-fold metrics that users scroll to. This combo preloads smartly without bloating initial load, delivering buttery-smooth experiences for managers eyeing KPIs without waiting forever.​&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Triggers and Sub-Blocks
&lt;/h2&gt;

&lt;p&gt;Angular’s &lt;code&gt;@defer&lt;/code&gt; blocks shine with built-in triggers like &lt;code&gt;idle&lt;/code&gt; (default, fires on browser idle via &lt;code&gt;requestIdleCallback&lt;/code&gt;), &lt;code&gt;viewport&lt;/code&gt; (loads on scroll into view using Intersection Observer), &lt;code&gt;interaction&lt;/code&gt; (triggers on click or keydown), &lt;code&gt;hover&lt;/code&gt; (on mouseover or focusin), &lt;code&gt;immediate&lt;/code&gt; (right after non-deferred content renders), and &lt;code&gt;timer&lt;/code&gt; (after specified ms or s). These use the &lt;code&gt;on&lt;/code&gt; keyword and support multiple via semicolons as OR conditions, decoupling prefetch from display for smarter loading.​&lt;/p&gt;

&lt;p&gt;Prefetching adds punch — load code early with &lt;code&gt;prefetch on idle&lt;/code&gt; (default) or others, separated by semicolon from main trigger, so resources wait ready without instant render. Picture an e-commerce dashboard: prefetch heavy charts on viewport entry, but show only on "View Analytics" button click—users get instant charts without upfront bloat.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Sub-Blocks for Seamless UX
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;@placeholder&lt;/code&gt; shows initial eagerly-loaded content (keep it lightweight—no heavy deps), with &lt;code&gt;minimum 500ms&lt;/code&gt; to dodge flicker on fast networks; it's required for some triggers like viewport needing a single root. &lt;code&gt;@loading&lt;/code&gt; kicks in post-trigger (replacing placeholder), eagerly loaded too, with &lt;code&gt;after 100ms; minimum 1s&lt;/code&gt; params to time it right—wait before show, ensure min display.​&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@error&lt;/code&gt; handles fetch fails gracefully, also eagerly loaded for quick fallback display. Wrap in &lt;code&gt;aria-live="polite"&lt;/code&gt; for screen reader announcements during swaps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Triggers with &lt;code&gt;when&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;For bespoke logic, &lt;code&gt;when&lt;/code&gt; takes signals or expressions like &lt;code&gt;@defer (when isVisible())&lt;/code&gt;—one-time truthy check, no revert. Combine with prefetch: &lt;code&gt;@defer (when userClicked(); prefetch when dataReady)&lt;/code&gt; for total control. In dashboards, signal on data fetch complete triggers charts post-interaction.​&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Patterns and Optimization
&lt;/h2&gt;

&lt;p&gt;Mastering &lt;code&gt;@defer&lt;/code&gt; goes beyond basics—it's about smart strategies that squeeze every millisecond from your app's performance. Think of it like a traffic controller for your JavaScript bundles: directing heavy loads only when needed, avoiding pile-ups that slow everything down. Let's dive into pro techniques that deliver real-world wins.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Nested &lt;a class="mentioned-user" href="https://dev.to/defer"&gt;@defer&lt;/a&gt; and Cascading Avoidance
&lt;/h3&gt;

&lt;p&gt;Nested &lt;code&gt;@defer&lt;/code&gt; blocks let you layer lazy loading for complex UIs, but stack them wrong and you trigger cascading requests—multiple bundles firing simultaneously, tanking load times. The fix? Stagger triggers: use &lt;code&gt;viewport&lt;/code&gt; for outer blocks and &lt;code&gt;interaction&lt;/code&gt; for inners. Combine with &lt;code&gt;@if&lt;/code&gt; for post-load toggling, like hiding loaded content until a condition flips true. This keeps your LCP snappy while giving granular control.​&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@defer (on viewport) {
  @defer (on interaction) {
    &amp;lt;heavy-chart /&amp;gt;
  } @placeholder {
    &amp;lt;div&amp;gt;Click to expand&amp;lt;/div&amp;gt;
  }
} @placeholder {
  &amp;lt;section&amp;gt;Scroll to see more&amp;lt;/section&amp;gt;
}
@if (isExpanded) {
  &amp;lt;summary-panel /&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SSR/SSG and Hydration Magic
&lt;/h3&gt;

&lt;p&gt;In SSR or SSG, servers render &lt;code&gt;@placeholder&lt;/code&gt; content (or nothing), skipping triggers since there's no viewport or idle state. Client-side, hydration kicks in, firing your configured triggers to make it interactive. Enable Incremental Hydration with &lt;code&gt;hydrate on&lt;/code&gt; triggers for server-rendered main content—perfect for SEO without bloating client bundles. Pro tip: pair &lt;code&gt;prefetch on idle&lt;/code&gt; to preload before hydration.​&lt;/p&gt;

&lt;h3&gt;
  
  
  Bundle Analysis and HMR Pitfalls
&lt;/h3&gt;

&lt;p&gt;Quantify &lt;code&gt;@defer&lt;/code&gt; wins with source-map-explorer: install via &lt;code&gt;npm i -D source-map-explorer&lt;/code&gt;, build with &lt;code&gt;ng build --source-map&lt;/code&gt;, then run &lt;code&gt;npx source-map-explorer dist/**/main.js&lt;/code&gt; for interactive treemaps showing chunk breakdowns. You'll see main bundles shrink as heavy standalone components split off—more accurate for Angular than alternatives. Watch for HMR gotchas—development servers eager-load all &lt;code&gt;@defer&lt;/code&gt; chunks, ignoring triggers; disable with &lt;code&gt;ng serve --no-hmr&lt;/code&gt; for accurate testing. Pitfall avoided, gains measured.​&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%2Fqdpus3uuqd0d70w69un5.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%2Fqdpus3uuqd0d70w69un5.png" alt="Tools for Measuring @defer Bundle Gains" width="746" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Accessibility with ARIA Live Regions
&lt;/h3&gt;

&lt;p&gt;Screen readers miss &lt;code&gt;@defer&lt;/code&gt; swaps—users hear placeholders but not loaded content. Wrap blocks in &lt;code&gt;aria-live="polite" aria-atomic="true"&lt;/code&gt; divs to announce transitions automatically. This keeps deferred UIs inclusive without extra JS, ensuring managers love the perf &lt;em&gt;and&lt;/em&gt; the ethics.​&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div aria-live="polite" aria-atomic="true"&amp;gt;
  @defer (on hover) { &amp;lt;user-profile /&amp;gt; }
  @placeholder { Loading profile... }
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Case Study
&lt;/h3&gt;

&lt;p&gt;One team slashed a 2MB Angular app into granular &lt;code&gt;@defer&lt;/code&gt; splits: charts on viewport, analytics on interaction. Result? Production LCP under 2s, CWV scores soaring. They measured with bundle analyzer, staggered nests, and added ARIA—proving &lt;code&gt;@defer&lt;/code&gt; scales from dashboards to enterprise dashboards.​&lt;/p&gt;

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

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/defer"&gt;@defer&lt;/a&gt; blocks deliver template-level code splitting through smart triggers like viewport, interaction, and idle, automatically creating separate JS chunks for standalone components, directives, and pipes — slashing initial bundle sizes and boosting Core Web Vitals such as LCP by up to 20–50% in real-world apps when paired with standalones.​&lt;/p&gt;

&lt;p&gt;This isn’t just theory: developers report main bundles dropping significantly (e.g., heavy chart components or third-party libs deferred until needed), leading to faster TTI and smoother user experiences without complex routing setups.​&lt;/p&gt;

&lt;p&gt;Unlike simple &lt;a class="mentioned-user" href="https://dev.to/if"&gt;@if&lt;/a&gt; hiding — which still downloads everything — &lt;a class="mentioned-user" href="https://dev.to/defer"&gt;@defer&lt;/a&gt; truly lazy-loads, prefetching on demand while handling placeholders, loading spinners, and errors gracefully.​&lt;/p&gt;

&lt;p&gt;Your support helps me create more practical guides and tools tailored for the frontend and startup community.&lt;/p&gt;

&lt;p&gt;Let’s keep building together 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>angular</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building a Modern Web Infrastructure with DigitalPlat and Cloudflare</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sat, 04 Apr 2026 12:18:45 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/building-a-modern-web-infrastructure-with-digitalplat-and-cloudflare-4m59</link>
      <guid>https://dev.to/gouranga-das-khulna/building-a-modern-web-infrastructure-with-digitalplat-and-cloudflare-4m59</guid>
      <description>&lt;p&gt;As a developer, having a personal domain and a solid infrastructure is essential for showcasing projects and building a professional brand. In this post, I will share how I managed to set up my web ecosystem using &lt;strong&gt;DigitalPlat FreeDomains&lt;/strong&gt; and &lt;strong&gt;Cloudflare&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🌟 Project Credit &amp;amp; Reference
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This project uses DigitalPlat FreeDomain, an open domain infrastructure maintained by Edward Hsing.&lt;/strong&gt; Built on DigitalPlat FreeDomain for domain provisioning, with credit to the platform and its maintainer for supporting global developers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why DigitalPlat?
&lt;/h2&gt;

&lt;p&gt;DigitalPlat provides a robust, open-domain infrastructure that is perfect for builders and creators. I am currently using several subdomains like gouranga.qzz.io and samrat.qzz.io to host my portfolio and development environments. The platform's commitment to providing free infrastructure for public-interest projects is truly commendable.&lt;/p&gt;
&lt;h2&gt;
  
  
  My Tech Stack
&lt;/h2&gt;

&lt;p&gt;To keep my projects fast, secure, and professional, I use the following tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Domain Provider:&lt;/strong&gt; DigitalPlat FreeDomains (Maintained by Edward Hsing).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS &amp;amp; Security:&lt;/strong&gt; Cloudflare (For SSL, DDoS protection, and CDN).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting:&lt;/strong&gt; GitHub Pages / Vercel (Integrated with my custom subdomains).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email:&lt;/strong&gt; Cloudflare Email Routing (To receive professional emails like &lt;a href="mailto:contact@samrat.qzz.io"&gt;contact@samrat.qzz.io&lt;/a&gt;).
## Step-by-Step Setup
### 1. Registering the Domain
I chose a name that reflects my identity, &lt;strong&gt;Gouranga Das Samrat&lt;/strong&gt;. DigitalPlat makes the registration process seamless. I simply picked a suffix (like .qzz.io) and pointed it to my nameservers.
### 2. Connecting to Cloudflare
Cloudflare is the backbone of my site's performance. By changing the nameservers in the DigitalPlat dashboard to Cloudflare's servers (e.g., ezra.ns.cloudflare.com and frida.ns.cloudflare.com), I gained full control over my DNS records, including A, CNAME, and MX records.
### 3. Implementing Email Routing
One of the coolest features I use is &lt;strong&gt;Cloudflare Email Routing&lt;/strong&gt;. It allows me to create custom email addresses for each of my domains without needing a dedicated mail server, redirecting everything to my personal Gmail.
## Current Progress &amp;amp; Future Plans
Currently, my main domain gouranga.qzz.io has reached over &lt;strong&gt;2,000 unique visitors&lt;/strong&gt;, which is an incredible milestone! Moving forward, I plan to:&lt;/li&gt;
&lt;li&gt;Launch a dedicated tech blog at gdsamrat.qzz.io.&lt;/li&gt;
&lt;li&gt;Set up a staging environment for my JavaScript projects at dev.gouranga.org.&lt;/li&gt;
&lt;li&gt;Document more about the DigitalPlat infrastructure to help fellow developers in Bangladesh.
## Conclusion
DigitalPlat is more than just a free domain provider; it's a gateway for developers in regions like Bangladesh to access world-class infrastructure for free. &lt;strong&gt;Special thanks to Edward Hsing and the DigitalPlat team&lt;/strong&gt; for their continuous support of the creator community!
&lt;em&gt;Published by **Gouranga Das Samrat&lt;/em&gt;**
&lt;em&gt;Visit my site: gouranga.qzz.io&lt;/em&gt;
&lt;a href="https://dash.domain.digitalplat.org/signup?ref=TCo24lqywE" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FDigitalPlat-Get%2520a%2520free%2520domain%2520from%2520DigitalPlat.-2563eb%3Fstyle%3Dflat-square%26logo%3Ddatabricks%26logoColor%3Dffffff" alt="Get a free domain from DigitalPlat." width="285" height="20"&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>🔥 Top Mistakes Developers Make While Applying for Jobs (And How to Fix Them)</title>
      <dc:creator>Gouranga Das Samrat</dc:creator>
      <pubDate>Sun, 29 Mar 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/gouranga-das-khulna/top-mistakes-developers-make-while-applying-for-jobs-and-how-to-fix-them-3471</link>
      <guid>https://dev.to/gouranga-das-khulna/top-mistakes-developers-make-while-applying-for-jobs-and-how-to-fix-them-3471</guid>
      <description>&lt;h2&gt;
  
  
  A Practical Guide to Standing Out in the Ultra-Competitive Tech Job Market in 2025
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The tech job market in 2025 is more competitive than ever. With thousands of developers applying for the same roles, many rejections happen&lt;/em&gt; &lt;strong&gt;&lt;em&gt;before&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;a recruiter even reads your resume. Not because you lack skills — but because small, avoidable mistakes weaken your application.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Here are the most common job-application mistakes developers make — and exactly how to fix them.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ 1. Using the Same Resume for Every Job
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Many developers create a single resume and use it everywhere — startups, MNCs, product companies, remote roles.&lt;br&gt;
But every company is looking for something different.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ How to Fix It
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Tailor your resume to the job description:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Add relevant keywords from the JD&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Highlight matching skills and tools&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Move the most relevant projects to the top&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Remove irrelevant experience&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Customizing your resume increases your chances of clearing ATS and impressing recruiters.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ 2. Writing Weak or Vague Project Descriptions
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;A line like:&lt;br&gt;
_**&lt;/em&gt;“Built a food delivery app using MERN.”&lt;em&gt;**&lt;/em&gt;&lt;br&gt;
…does nothing to help you stand out._&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Recruiters want clarity — what exactly did you do? What problem did you solve? What impact did it create?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ How to Fix It
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Use the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Action + Impact&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;formula.&lt;br&gt;
Example:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;_“Developed a MERN-based food delivery platform with real-time order tracking, reducing average delivery time by 20%.”&lt;br&gt;
_&lt;/strong&gt;&lt;em&gt;This immediately shows your contribution, skill, and measurable value.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ 3. Ignoring Achievements and Metrics
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Most resumes read like job descriptions:&lt;br&gt;
“Worked on frontend UI. Integrated APIs. Wrote backend services.”&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Richa Gautam 🌷’s stories in your inbox
&lt;/h2&gt;

&lt;p&gt;Join Medium for free to get updates from this writer.&lt;/p&gt;

&lt;p&gt;Subscribe&lt;/p&gt;

&lt;p&gt;Subscribe&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But companies hire people who deliver&lt;/em&gt; &lt;strong&gt;&lt;em&gt;results&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;, not tasks.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ How to Fix It
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Add numbers and measurable outcomes:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Increased user sign-ups by&lt;/em&gt; &lt;strong&gt;&lt;em&gt;25%&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Improved website performance by&lt;/em&gt; &lt;strong&gt;&lt;em&gt;40%&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Automated testing saved&lt;/em&gt; &lt;strong&gt;&lt;em&gt;6+ hours per week&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Reduced customer complaints by&lt;/em&gt; &lt;strong&gt;&lt;em&gt;15%&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Metrics instantly make your resume more credible and memorable.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ 4. Having an Inactive GitHub or LinkedIn
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Recruiters almost always check your online presence.&lt;br&gt;
An empty GitHub or outdated LinkedIn creates the impression that you’ve stopped learning.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ How to Fix It
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Keep your digital presence alive:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Update your pinned repositories&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Add a short, clear “About” section&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Post weekly insights, project updates, or coding learnings on LinkedIn&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Consistency shows curiosity — one of the most valued traits in tech teams.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ 5. Never Following Up After Applying
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Many developers apply once and wait.&lt;br&gt;
Your email may simply get buried — not rejected.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ How to Fix It
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Send a polite follow-up after 3–5 days:&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Hi [Name], just following up on my application for [Role].&lt;br&gt;
I’m genuinely excited about the opportunity at [Company] and would love to discuss how my experience aligns with your needs.”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;This small gesture dramatically increases your chances of getting noticed.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Bonus: Underestimating the Power of Personal Branding
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;In 2025, your resume is just one piece of your professional identity.&lt;br&gt;
Recruiters also look at:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Your portfolio&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Your GitHub&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Your LinkedIn posts&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Your side projects&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Your problem-solving approach&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ✅ How to Fix It
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Show your learning journey:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Share mini-projects&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Write about debugging problems&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Post your coding insights&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;em&gt;Document your growth&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Personal branding builds trust even before the interview begins.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Your technical skills matter — but&lt;/em&gt; &lt;strong&gt;&lt;em&gt;how you present them&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;matters even more.&lt;br&gt;
A few intentional changes to your resume, project descriptions, and online presence can drastically improve your job search results.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Start today.&lt;br&gt;
You’ll see the difference within a week.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🙏 Stay Connected!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;🔔 Follow for more guides on JavaScript, React.js &amp;amp; interview prep.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;**_Thankyou! for reading my article.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
