<?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: Hamid Shoja</title>
    <description>The latest articles on DEV Community by Hamid Shoja (@hash01).</description>
    <link>https://dev.to/hash01</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%2F538427%2Fb88dc832-018a-41a3-ad11-7dc58f0f15b1.jpeg</url>
      <title>DEV Community: Hamid Shoja</title>
      <link>https://dev.to/hash01</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hash01"/>
    <language>en</language>
    <item>
      <title>A tip from a senior engineer</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Mon, 19 Jan 2026 18:12:06 +0000</pubDate>
      <link>https://dev.to/hash01/a-tip-from-a-senior-engineer-3pe9</link>
      <guid>https://dev.to/hash01/a-tip-from-a-senior-engineer-3pe9</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/hash01" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F538427%2Fb88dc832-018a-41a3-ad11-7dc58f0f15b1.jpeg" alt="hash01"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/hash01/the-trade-off-clean-testing-vs-code-brevity-in-modern-js-12k0" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;The Trade-off: Clean Testing vs. Code Brevity in Modern JS&lt;/h2&gt;
      &lt;h3&gt;Hamid Shoja ・ Jan 19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#backend&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>node</category>
      <category>backend</category>
    </item>
    <item>
      <title>Uvicorn in Modern Python APIs</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Mon, 19 Jan 2026 18:10:24 +0000</pubDate>
      <link>https://dev.to/hash01/uvicorn-in-modern-python-apis-4m79</link>
      <guid>https://dev.to/hash01/uvicorn-in-modern-python-apis-4m79</guid>
      <description>&lt;p&gt;A quick guide to why Uvicorn is essential for Python developers in 2026, how to use it, and how it stacks up against other languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Uvicorn?
&lt;/h2&gt;

&lt;p&gt;Uvicorn is a high-speed ASGI (Asynchronous Server Gateway Interface) server. While frameworks like FastAPI or Starlette help you write your code, Uvicorn is the "engine" that actually runs the code and handles web requests from users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we use it?
&lt;/h2&gt;

&lt;p&gt;In the past, Python servers (WSGI) could only handle one request at a time per process. Uvicorn uses an asynchronous event loop, allowing it to handle thousands of concurrent connections (like WebSockets or long-polling) without waiting for one to finish before starting the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start Example
&lt;/h2&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Code (main.py):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http.response.start&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content-type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text/plain&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http.response.body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello, Dev.to!&lt;/span&gt;&lt;span class="sh"&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;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn main:app &lt;span class="nt"&gt;--reload&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Alternatives to Consider
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Hypercorn&lt;/code&gt;: Great if you need HTTP/3 support.&lt;br&gt;
&lt;code&gt;Daphne&lt;/code&gt;: The go-to for Django Channels.&lt;br&gt;
&lt;code&gt;Granian&lt;/code&gt;: A Rust-based runner for those who need even more speed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture Comparison (Python vs. The World)
&lt;/h2&gt;

&lt;p&gt;How does Uvicorn's "Event Loop" compare to other languages in 2026?&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%2Faa9talvw8flc9n05wz1f.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%2Faa9talvw8flc9n05wz1f.png" alt=" " width="626" height="385"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Perfomance
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Unicorn&lt;/strong&gt;: ~150k requests/sec; excellent for I/O but limited by the Global Interpreter Lock (GIL).&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Nodejs&lt;/strong&gt;: ~600k requests/sec; highly optimized for I/O-bound web traffic.&lt;br&gt;
&lt;strong&gt;Go (Goroutines)&lt;/strong&gt;: &amp;gt;1M requests/sec; built-in concurrency makes it a "workhorse" for microservices.&lt;br&gt;
&lt;strong&gt;Rust (Tokio/Axum)&lt;/strong&gt;: &amp;gt;1M requests/sec; the fastest model due to lack of garbage collection and zero-cost abstractions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cpu-intensive tasks
&lt;/h2&gt;

&lt;p&gt;In a single-threaded async loop, one heavy CPU calculation can freeze the entire server. We should offload blocking tasks to a thread pool or a separate worker (like Celery/Arq) to keep the Uvicorn loop responsive.&lt;/p&gt;

&lt;p&gt;Example: Use run_in_executor for blocking code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/heavy-task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;heavy_task&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Don't run blocking code directly; offload it to keep the loop free
&lt;/span&gt;    &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_running_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_in_executor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;some_blocking_heavy_math&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;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;If you are building a modern Python web app, &lt;code&gt;Uvicorn&lt;/code&gt; is the standard choice. It balances the ease of Python with the speed required for modern, real-time web applications.&lt;/p&gt;

&lt;p&gt;Follow for more bite-sized dev tutorials! 🚀&lt;br&gt;
HASH&lt;/p&gt;

&lt;p&gt;refs:&lt;br&gt;
&lt;a href="https://medium.com/@yogeshkrishnanseeniraj/scaling-django-async-workers-uvicorn-gunicorn-celery-and-redis-full-benchmarking-guide-fef057069e96#:%7E:text=Uvicorn%20alone%20provides%20excellent%20async,with%20low%20to%20moderate%20traffic" rel="noopener noreferrer"&gt;https://medium.com/@yogeshkrishnanseeniraj/scaling-django-async-workers-uvicorn-gunicorn-celery-and-redis-full-benchmarking-guide-fef057069e96#:~:text=Uvicorn%20alone%20provides%20excellent%20async,with%20low%20to%20moderate%20traffic&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/21485920/single-threaded-event-loop-vs-multi-threaded-non-blocking-worker-in-node-js#:%7E:text=As%20a%20minor%20addendum%20I,57.8k10%2093%20131" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/21485920/single-threaded-event-loop-vs-multi-threaded-non-blocking-worker-in-node-js#:~:text=As%20a%20minor%20addendum%20I,57.8k10%2093%20131&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=n0KETvEqiCk&amp;amp;t=57" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=n0KETvEqiCk&amp;amp;t=57&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>python</category>
      <category>ai</category>
    </item>
    <item>
      <title>The Trade-off: Clean Testing vs. Code Brevity in Modern JS</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Mon, 19 Jan 2026 17:57:48 +0000</pubDate>
      <link>https://dev.to/hash01/the-trade-off-clean-testing-vs-code-brevity-in-modern-js-12k0</link>
      <guid>https://dev.to/hash01/the-trade-off-clean-testing-vs-code-brevity-in-modern-js-12k0</guid>
      <description>&lt;p&gt;Hey fellow devs! 👋&lt;/p&gt;

&lt;p&gt;In modern JavaScript and TypeScript development, we are constantly balancing two opposing forces: the desire for &lt;strong&gt;Code Brevity&lt;/strong&gt; (writing concise, minimal code) and the need for &lt;strong&gt;Clean Testing&lt;/strong&gt; (writing code that is easy to isolate and verify).&lt;/p&gt;

&lt;p&gt;Often, the code that is fastest to write is the hardest to test.&lt;/p&gt;

&lt;p&gt;Conversely, code designed for testability often looks "boilerplate-heavy" at first glance.&lt;/p&gt;

&lt;p&gt;Let's explore this trade-off through real-world examples, moving from common patterns to the mindset required for architecting long-term scalable systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Round 1: The Environment Variable Dilemma
&lt;/h2&gt;

&lt;p&gt;This is a classic debate that often appears in code reviews. How do you access environment variables like API keys or feature flags provided by Vite, Webpack, or Node?&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Brief" Approach (Static Constants)
&lt;/h3&gt;

&lt;p&gt;The fastest way is to read the variable directly and store it in a constant. It's one line of code. It's simple.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IS_PRODUCTION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PROD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_URL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// myFeature.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IS_PRODUCTION&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;IS_PRODUCTION&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do scary real things&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Hidden Cost
&lt;/h3&gt;

&lt;p&gt;This code is brief, but it is tightly coupled to the build system's global state.&lt;/p&gt;

&lt;p&gt;When you write a unit test for &lt;code&gt;myFeature.ts&lt;/code&gt;, the &lt;code&gt;IS_PRODUCTION&lt;/code&gt; constant is evaluated immediately when the test file loads. Once that constant is set to &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;, it is extremely difficult to change it within the same test suite run.&lt;/p&gt;

&lt;p&gt;To test both scenarios, you often have to resort to "stubbing globally" , telling your test runner (like Vitest or Jest) to fundamentally alter how the JavaScript runtime behaves.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Messy Global Testing&lt;/span&gt;
&lt;span class="nx"&gt;vi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stubEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PROD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// Now EVERY test thinks it's prod until you remember to unstub it.&lt;/span&gt;
&lt;span class="c1"&gt;// If you forget, other tests break mysteriously.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The "Testable" Approach (Getter Functions)
&lt;/h3&gt;

&lt;p&gt;The alternative is to wrap the access in a function. It adds boilerplate. It feels slightly redundant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config.ts&lt;/span&gt;
&lt;span class="c1"&gt;// It's just a function returning a value&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getIsProduction&lt;/span&gt; &lt;span class="o"&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="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PROD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// myFeature.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getIsProduction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// We call the function now&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getIsProduction&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do scary real things&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Benefit: Creating a "Seam"
&lt;/h3&gt;

&lt;p&gt;From a Senior Engineering perspective, we have just created a Seam.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fwiki.c2.com%2F%3FSoftwareSeam" rel="noopener noreferrer"&gt;Seam&lt;/a&gt; is a concept (popularized by Michael Feathers) referring to a place where you can alter the behavior of your program without editing the source code.&lt;/p&gt;

&lt;p&gt;In our tests, we no longer need to hack the global environment. We just need to spy on a standard JavaScript function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Clean Isolated Testing&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;does scary things only in prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Create the seam just for this test block&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getIsProduction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// run expectations...&lt;/span&gt;
  &lt;span class="nx"&gt;spy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockReturnValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// run other expectations...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The testable approach trades brevity for isolation and control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Round 2: Dealing with Time
&lt;/h2&gt;

&lt;p&gt;Another common area where brevity hurts testing is handling current time.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Brief" Approach (Direct Access)
&lt;/h3&gt;

&lt;p&gt;Imagine a function that determines if a discount code is expired.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// discount.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDiscountExpired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expiryDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Brevity wins here:&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;expiryDate&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 code is incredibly short. But it is non-deterministic.&lt;/p&gt;

&lt;p&gt;If you write a test today that says "Expires tomorrow should return false", that test will pass today. But if you run that same test suite tomorrow, it will fail.&lt;/p&gt;

&lt;p&gt;To test this, you again have to rely on heavy-handed global tool hacks like "Fake Timers" to freeze the system clock of the test runner.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Testable" Approach (Dependency Injection)
&lt;/h3&gt;

&lt;p&gt;To make this testable, we need to take control away from the function itself and inject the dependency (time).&lt;/p&gt;

&lt;p&gt;We can do this via a defaulted parameter (a lightweight form of Dependency Injection).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// discount.ts&lt;/span&gt;
&lt;span class="c1"&gt;// We allow 'now' to be passed in, but default to current time&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDiscountExpired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;expiryDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Default value makes it easy to use in app code&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;expiryDate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the test is trivial and deterministic. We don't need to freeze system time; we just pass in a fixed date.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Clean Testing&lt;/span&gt;
&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checks expiration&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fixedNow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2024-01-01T10:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tomorrow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2024-01-02T10:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// We inject our fixed time, guaranteeing the result forever&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isDiscountExpired&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tomorrow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fixedNow&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;h2&gt;
  
  
  The Senior Engineer's Mindset
&lt;/h2&gt;

&lt;p&gt;When you are a junior or mid-level developer, your primary metric is often "velocity" , how fast can I ship this feature? Brevity helps velocity in the short term.&lt;/p&gt;

&lt;p&gt;As you advance to senior or principal roles, your primary metrics shift to &lt;strong&gt;maintainability, stability, and risk reduction.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Shift Left
&lt;/h2&gt;

&lt;p&gt;We want to "shift left" on bugs ,  finding them during unit tests on a developer's machine, rather than in QA or production.&lt;/p&gt;

&lt;p&gt;If code is brief but relies on global state (like &lt;code&gt;import.meta.env&lt;/code&gt; or &lt;code&gt;new Date())&lt;/code&gt;, developers will instinctively avoid writing tests for it because writing those tests is difficult and painful.&lt;/p&gt;

&lt;p&gt;By introducing slight amounts of boilerplate , creating getter functions, injecting dependencies, creating seams ,  we lower the friction required to write a test.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose Brevity&lt;/strong&gt; for throwaway prototypes, simple scripts, or incredibly confined UI components that have zero logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose Testability&lt;/strong&gt; for business logic, configuration, helpers, and anything that your application relies on to function correctly over time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It looks like more code today, but it buys you peace of mind tomorrow.&lt;/p&gt;

&lt;p&gt;If this helped, give it a heart!&lt;br&gt;
Hash&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>node</category>
      <category>backend</category>
    </item>
    <item>
      <title>Understanding MCP Through a Simple Example: A Practical Introduction</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Sat, 17 Jan 2026 18:41:59 +0000</pubDate>
      <link>https://dev.to/hash01/understanding-mcp-through-a-simple-example-a-practical-introduction-3bp7</link>
      <guid>https://dev.to/hash01/understanding-mcp-through-a-simple-example-a-practical-introduction-3bp7</guid>
      <description>&lt;p&gt;Hey fellow devs! 👋&lt;/p&gt;

&lt;p&gt;I’ve been working with MCP fairly often and like most of us, I learn best by actually building something. Not something production-ready or revolutionary — just something simple enough to understand what MCP actually does.&lt;/p&gt;

&lt;p&gt;That’s why I built a basic currency converter using MCP. It’s intentionally simple, but that’s the point.&lt;/p&gt;

&lt;p&gt;Let me walk you through what can be learned from this example.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Personal Take First
&lt;/h2&gt;

&lt;p&gt;When new protocols and frameworks come out, I want to answer one question: “What problem does this actually solve?”&lt;/p&gt;

&lt;p&gt;This currency converter teaches exactly how MCP works, and that’s worth sharing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Learning Goal
&lt;/h2&gt;

&lt;p&gt;Before writing any code, I want you to understand one specific thing:&lt;/p&gt;

&lt;p&gt;How does AI actually communicate with external tools through MCP?&lt;/p&gt;

&lt;h2&gt;
  
  
  What MCP Actually Does
&lt;/h2&gt;

&lt;p&gt;Here’s what I learned by building this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without MCP:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Is ¥10,000 enough to buy a $60 game?"
AI: "I don't have access to current exchange rates, 
     but you can check [some website]."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With MCP:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Is ¥10,000 enough to buy a $60 game?"
AI: 
1. Realizes it needs an exchange rate
2. Sees there's a get_exchange_rate tool available
3. Calls: get_exchange_rate(from="JPY", to="USD", amount=10000)
4. Gets: 10000 JPY = 65.83 USD
5. Responds: "Yes, ¥10,000 is approximately $65.83 USD, 
              so you'd have $5.83 left after buying the game."

The key insight: MCP is just a standardized way for AI to discover and use your tools.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Example Architecture
&lt;/h2&gt;

&lt;p&gt;My simple implementation looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User sends natural language prompt&lt;/li&gt;
&lt;li&gt;Hono API receives it&lt;/li&gt;
&lt;li&gt;API gets list of provided MCP server tools (&lt;code&gt;get_exchange_rate&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;API Sends prompt + tools to Claude AI &lt;/li&gt;
&lt;li&gt;Claude AI interprets when user wants a tool&lt;/li&gt;
&lt;li&gt;In the interception step API calls MCP tool, getting the actual rate&lt;/li&gt;
&lt;li&gt;API sends another request to Claude AI including actual rate + prompt&lt;/li&gt;
&lt;li&gt;User gets their answer
It’s basic. And that’s exactly why it’s useful for learning.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Look at the MCP tool definition:
&lt;/h2&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="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"get_exchange_rate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;description:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Get exchange rate between currencies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;inputSchema:&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="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;properties:&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="err"&gt;from_currency:&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="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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="err"&gt;to_currency:&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="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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="err"&gt;amount:&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="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;optional:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tool just returns exchange rates. That’s it.&lt;/p&gt;

&lt;p&gt;The AI takes care of everything else.&lt;/p&gt;

&lt;p&gt;Now Let’s take a closer look at the implementation steps together.&lt;/p&gt;

&lt;p&gt;1- User sends natural language prompt&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Is ¥10,000 enough to buy a $60 game?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- API receives it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- API gets list of provided MCP server tools (get_exchange_rate)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mcpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listTools&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="nx"&gt;Sends&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Claude&lt;/span&gt; &lt;span class="nx"&gt;AI&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&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;5- Claude AI interprets When user wants an action that provided in tools get_exchange_rate&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop_reason&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tool_use&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolUse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;block&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tool_use&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6- In the interception step API calls MCP tool, getting the actual rate&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mcpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolUse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolUse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&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;7- API sends another request to Claude AI including actual rate + prompt&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;messages&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="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// original prompt&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
              &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tool_result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;tool_use_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolUse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toolResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// rate info&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;8- User gets their answer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;finalText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;finalText&lt;/span&gt; 

&lt;span class="c1"&gt;// Yes, ¥10,000 is approximately $65.83 USD, &lt;/span&gt;
&lt;span class="c1"&gt;//              so you'd have $5.83 left after buying the game&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Simple Example Matters
&lt;/h2&gt;

&lt;p&gt;Here’s what this simple example demonstrates:&lt;/p&gt;

&lt;p&gt;1.** Tool Discovery**&lt;br&gt;
The AI can see what tools are available and understand when to use them based on the description.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parameter Extraction&lt;/strong&gt;
The AI automatically extracts structured parameters from messy natural language:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“Is ¥10,000 enough for $60?” → from="JPY", to="USD", amount=10000
“How many dollars is 50 euros?” → from="EUR", to="USD", amount=50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Context Awareness&lt;/strong&gt;
The AI can handle complex queries:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“I have 5 euros in cash and 20 in my bank, total in USD?”
AI does: 5 + 20 = 25, then calls the tool with 25 EUR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Natural Responses&lt;/strong&gt;
The AI formats the tool’s response naturally instead of just dumping JSON.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  See It Working
&lt;/h2&gt;

&lt;p&gt;I recorded a quick demo showing different types of queries being handled:&lt;/p&gt;

&lt;p&gt;Press enter or click to view image in full size&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%2F6die6pigf3m6qlkdj5ou.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6die6pigf3m6qlkdj5ou.gif" alt=" " width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nothing fancy, just the basic flow working as expected.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting It Up (For Learning Purposes)
&lt;/h2&gt;

&lt;p&gt;If you want to try this yourself to understand MCP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/hshoja/Currency-Exchange-MCP-Service
npm install
cp env.example .env
# Add your API keys to .env
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You’ll need:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://console.anthropic.com/" rel="noopener noreferrer"&gt;Anthropic API key&lt;/a&gt; (for Claude AI)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://freecurrencyapi.com/" rel="noopener noreferrer"&gt;Freecurrencyapi key&lt;/a&gt; (for exchange rates)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then just send POST requests with natural language prompts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "prompt": "What is 100 USD in EUR?"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Real Takeaway
&lt;/h2&gt;

&lt;p&gt;After building this simple example, We now understand:&lt;/p&gt;

&lt;p&gt;MCP is not about building smarter APIs.&lt;/p&gt;

&lt;p&gt;It’s about building simple, focused tools and letting AI be the smart layer that connects them to human intent.&lt;/p&gt;

&lt;p&gt;Your tool can be dumb. It should be dumb. Just do one thing well, and let AI the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Potential Use Cases (Beyond This Simple Example)
&lt;/h2&gt;

&lt;p&gt;While the currency converter is basic, the pattern scales to more interesting problems, have a look to these examples.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=09tJS0ZEHms" rel="noopener noreferrer"&gt;AI Agent Crypto MCP Trading&lt;/a&gt;&lt;/strong&gt; : an example which shows how create an mcp that opens or closes positions in a crypto platform by natural language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=GuTcle5edjk&amp;amp;t=1399s" rel="noopener noreferrer"&gt;Kali Linux HACKING MCP&lt;/a&gt;&lt;/strong&gt; : running kali commands for hacking by natural language&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=eur8dUO9mvE" rel="noopener noreferrer"&gt;Natural language to SQL&lt;/a&gt;&lt;/strong&gt;: connect and query the database by natural language&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=FLpS7OfD5-s&amp;amp;t=390s" rel="noopener noreferrer"&gt;Building an agentic appointment scheduling ap&lt;/a&gt;p&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The complexity isn’t in MCP itself — it’s in the tools you build and connect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check Out The Code
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/hshoja/Currency-Exchange-MCP-Service" rel="noopener noreferrer"&gt;full repository&lt;/a&gt; includes:&lt;/p&gt;

&lt;p&gt;Feel free to clone it, modify it, or use it as a reference while learning MCP yourself.&lt;/p&gt;

&lt;p&gt;Are you learning MCP too? Have you built simple examples to understand new tech? I’d love to hear about it — drop a comment!&lt;/p&gt;

&lt;p&gt;P.S. — If this helped you understand MCP a bit better, give it a like! And remember: simple examples are valid examples.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>webdev</category>
      <category>node</category>
      <category>ai</category>
    </item>
    <item>
      <title>How simultaneously swapping unique IDs in Postgres</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Mon, 08 Dec 2025 18:29:05 +0000</pubDate>
      <link>https://dev.to/hash01/how-simultaneously-swapping-unique-ids-in-postgres-1ki5</link>
      <guid>https://dev.to/hash01/how-simultaneously-swapping-unique-ids-in-postgres-1ki5</guid>
      <description>&lt;p&gt;Hi friends&lt;/p&gt;

&lt;p&gt;Here's a quick tip for when you're working with Postgres, this came in clutch for me when I had to use &lt;code&gt;DEFERRABLE INITIALLY IMMEDIATE&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I'm sharing this with a practical example where two rows in a table must exchange unique values simultaneously within the same transaction. This is common when swapping unique IDs or handling cyclic dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Swapping Unique Teacher IDs
&lt;/h3&gt;

&lt;p&gt;Consider a classes table where each class has a unique &lt;code&gt;teacher_id&lt;/code&gt;, but you need to swap the teachers between two classes. The UNIQUE constraint would normally prevent this in a single &lt;code&gt;UPDATE&lt;/code&gt; statement because, mid-operation, there would temporarily be duplicate &lt;code&gt;teacher_id&lt;/code&gt; values.&lt;/p&gt;

&lt;p&gt;So we can Define the table with a unique constraint that is &lt;code&gt;DEFERRABLE INITIALLY IMMEDIATE&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;teacher_id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;DEFERRABLE&lt;/span&gt; &lt;span class="k"&gt;INITIALLY&lt;/span&gt; &lt;span class="k"&gt;IMMEDIATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;-- Insert initial data&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Biology'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Chemistry'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the database checks the uniqueness after every statement.&lt;br&gt;
Perform the swap within a transaction by explicitly deferring the constraint check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Temporarily set the specific constraint to DEFERRED mode for this transaction&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINTS&lt;/span&gt; &lt;span class="n"&gt;classes_teacher_id_key&lt;/span&gt; &lt;span class="k"&gt;DEFERRED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- The update statements can now run without immediate failure&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;teacher_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;102&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- Temporarily creates duplicate 102&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;classes&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;teacher_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- Resolves the duplicate&lt;/span&gt;

&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- At the COMMIT point, the database checks all deferred constraints.&lt;/span&gt;
&lt;span class="c1"&gt;-- Since the final state is valid (101 and 102 are unique again), the transaction succeeds.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you tried these updates without the BEGIN; ... SET CONSTRAINTS DEFERRED; ... COMMIT; block, the first UPDATE statement would immediately fail due to the INITIALLY IMMEDIATE setting, which acts as a per-statement check.&lt;/p&gt;

&lt;p&gt;this example demonstrate how to use &lt;code&gt;DEFERRABLE INITIALLY IMMEDIATE&lt;/code&gt; constraints to swap unique values within a transaction:&lt;/p&gt;

&lt;p&gt;Hope that helped! &lt;/p&gt;

&lt;p&gt;Hash&lt;/p&gt;

</description>
      <category>sql</category>
      <category>postgres</category>
    </item>
    <item>
      <title>React 19.2's useEffectEvent vs our Custom useEventCallback</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Sun, 05 Oct 2025 13:02:20 +0000</pubDate>
      <link>https://dev.to/hash01/react-192s-useeffectevent-vs-our-custom-useeventcallback-i45</link>
      <guid>https://dev.to/hash01/react-192s-useeffectevent-vs-our-custom-useeventcallback-i45</guid>
      <description>&lt;p&gt;Hey fellow React devs! 👋&lt;/p&gt;

&lt;p&gt;So React 19.2 dropped and brought us &lt;code&gt;useEffectEvent&lt;/code&gt; - a new hook that solves a problem many of us have been tackling with custom solutions. If you're like me and have been using a custom &lt;code&gt;useEventCallback&lt;/code&gt; hook (or something similar), you're probably wondering: "Should I ditch my trusty custom hook for this new official one?"&lt;/p&gt;

&lt;p&gt;BTW: &lt;a href="https://hamid-shoja.medium.com/react-19-2s-useeffectevent-vs-our-custom-useeventcallback-e96b9ce3811e" rel="noopener noreferrer"&gt;if you interested to read it from medium.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me break it down for you based on some real-world experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Both Hooks Solve
&lt;/h2&gt;

&lt;p&gt;First, let's talk about why these hooks exist. You know that annoying situation where you want to access the latest state/props/reference in a &lt;code&gt;useEffect&lt;/code&gt; without adding them to the dependency array? Yeah, that one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ShoppingCartContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberOfItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onNavigate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;visitedUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;logVisit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visitedUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;numberOfItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},[&lt;/span&gt;&lt;span class="nx"&gt;numberOfItems&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;onNavigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onNavigate&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// if not passing onNavigate getting lint error&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the Effect should re-run after a render when &lt;code&gt;url&lt;/code&gt; changes (to log the new page visit), but it should &lt;strong&gt;not&lt;/strong&gt; re-run when &lt;code&gt;numberOfItems&lt;/code&gt; changes that creates a new ref for &lt;code&gt;onNavigate&lt;/code&gt; causing new log for every &lt;code&gt;numberOfItems&lt;/code&gt; up and down!&lt;/p&gt;

&lt;p&gt;So we need a way to get a persistent ref for &lt;code&gt;onNavigate&lt;/code&gt; function including the latest &lt;code&gt;numberOfItems&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now if you use new hook &lt;code&gt;useEffectEvent&lt;/code&gt; instead of &lt;code&gt;useCallback&lt;/code&gt; this problem gets solved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ShoppingCartContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberOfItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onNavigate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEffectEvent&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;visitedUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;logVisit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visitedUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;numberOfItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;onNavigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&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 problem already gets solved by another hook called &lt;code&gt;useEventCallback&lt;/code&gt; by creating stable function reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet the Custom Champion: useEventCallback
&lt;/h2&gt;

&lt;p&gt;This is what many of us have been building:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useEventCallback&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;extends &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;((...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&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 reliable, battle-tested, and works everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  CAN We Now Swap Them?
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. These hooks are &lt;strong&gt;not&lt;/strong&gt; drop-in replacements for each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  useEventCallback instead of useEffectEvent:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Yes you can&lt;/strong&gt;, the result is almost the same, example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ShoppingCartContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberOfItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onNavigate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEventCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;visitedUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;logVisit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;visitedUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;numberOfItems&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;onNavigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there are some caveats:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;React's internal magic &amp;gt; our clever hacks&lt;/strong&gt;, so maybe we're missing some React optimizations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The official API is designed for React's future&lt;/strong&gt; - You need perfect Concurrent Mode compliance&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  useEffectEvent instead of useEventCallback:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  ✅ You CAN use useEffectEvent when you need stable event handlers for Effect deps
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ useEffectEvent works&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEventCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nf"&gt;handleClick&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;h4&gt;
  
  
  ❌ You CANNOT use useEffectEvent when:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. You need event handlers for JSX&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ useEventCallback works&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEventCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Click&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;
&lt;span class="c1"&gt;// ❌ useEffectEvent is NOT for this&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. You're passing callbacks to child components&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Safe with useEventCallback&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onChildEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEventCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handleChildEvent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChildComponent&lt;/span&gt; &lt;span class="nx"&gt;onEvent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChildEvent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;
&lt;span class="c1"&gt;// ❌ Don't pass useEffectEvent callbacks as props&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. You need async operations&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ useEventCallback handles async fine&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEventCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// ❌ useEffectEvent has restrictions with async&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  My Take: Use Both (For Now)
&lt;/h2&gt;

&lt;p&gt;Here's my practical recommendation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep using &lt;code&gt;useEventCallback&lt;/code&gt;&lt;/strong&gt; for general stable function references, event handlers, and callback props&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adopt &lt;code&gt;useEffectEvent&lt;/code&gt;&lt;/strong&gt; specifically for functions called within effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They serve different purposes, even though they solve similar problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Migration Path
&lt;/h2&gt;

&lt;p&gt;If you're on React 19.2+, start migrating effect-specific uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEventCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;logEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someData&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="nx"&gt;someData&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// After&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logEvent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEffectEvent&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;logEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;someData&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="nx"&gt;someData&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But keep &lt;code&gt;useEventCallback&lt;/code&gt; for everything else!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Don't feel bad about your custom hook - it's been doing great work! &lt;code&gt;useEffectEvent&lt;/code&gt; isn't here to replace it entirely, but to provide a more specialized, optimized solution for a specific use case.&lt;/p&gt;

&lt;p&gt;What's your experience been with these hooks? Are you planning to migrate, or sticking with your custom solutions? Drop a comment - I'd love to hear your thoughts!&lt;/p&gt;

</description>
      <category>react</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>7 Essential grep commands for software engineers</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Mon, 15 Jul 2024 07:02:52 +0000</pubDate>
      <link>https://dev.to/hash01/7-essential-grep-command-for-software-engineers-19b3</link>
      <guid>https://dev.to/hash01/7-essential-grep-command-for-software-engineers-19b3</guid>
      <description>&lt;p&gt;I'd like to share a quick review of 7 essential grep commands that every software engineer should know and use in their daily work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commands covered:
&lt;/h3&gt;

&lt;p&gt;Recursive search&lt;br&gt;
Display line numbers&lt;br&gt;
Display filenames&lt;br&gt;
Invert match&lt;br&gt;
Multiple Patterns &lt;br&gt;
Context of matching lines&lt;br&gt;
Use regular expressions&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search for a pattern in all files recursively:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -r "pattern" /path/to/directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Display line numbers along with matching lines:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -n "pattern" filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Display only the names of files with matching lines:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -l "pattern" *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Invert match (display non-matching lines):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -v "pattern" filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Search for multiple patterns:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -e "pattern1" -e "pattern2" filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Show the context of matching lines (before and after):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -C 3 "pattern" filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Use regular expressions for complex patterns:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -E "pattern1|pattern2" filename
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Best&lt;br&gt;
HASH &lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>linux</category>
      <category>cli</category>
    </item>
    <item>
      <title>Bumping the Node.js version to higher version</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Mon, 01 Jul 2024 14:06:07 +0000</pubDate>
      <link>https://dev.to/hash01/bumping-the-nodejs-version-to-higher-version-55i</link>
      <guid>https://dev.to/hash01/bumping-the-nodejs-version-to-higher-version-55i</guid>
      <description>&lt;p&gt;Before bumping the Node.js version to higher version in your package.json, you should consider the following:&lt;/p&gt;

&lt;h2&gt;
  
  
  Check Node.js Release Schedule:
&lt;/h2&gt;

&lt;p&gt;The Node.js release schedule is available at &lt;a href="https://nodejs.org/en/about/releases/" rel="noopener noreferrer"&gt;https://nodejs.org/en/about/releases/&lt;/a&gt;. You should use a version that is currently maintained.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check Dependencies Compatibility:
&lt;/h2&gt;

&lt;p&gt;Ensure that all your dependencies are compatible with the new Node.js version. You can check the engines field in the package.json of your dependencies, or check their documentation.&lt;/p&gt;

&lt;p&gt;There are some methods to check this but you also can use this script to check all packages' engine&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;packageJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allDependencies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;devDependencies&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dependency&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;allDependencies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`npm view &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dependency&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; engines`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`exec error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Engines for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dependency&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Update Your Development Environment:
&lt;/h2&gt;

&lt;p&gt;Make sure that your local development environment is running the same Node.js version. You can use a version manager like nvm to manage multiple Node.js versions on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update Your CI/CD Pipeline:
&lt;/h2&gt;

&lt;p&gt;If you have a continuous integration/continuous deployment (CI/CD) pipeline, make sure to update the Node.js version there as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inform Your Team:
&lt;/h2&gt;

&lt;p&gt;If you're working in a team, inform everyone about the Node.js version change so they can update their local environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Your Application:
&lt;/h2&gt;

&lt;p&gt;After updating the Node.js version, thoroughly test your application to catch any potential issues caused by the version change.&lt;/p&gt;

&lt;p&gt;Here's how you can update the Node.js version to &lt;code&gt;20&lt;/code&gt; in your package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"engines"&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;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=20"&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;Thank you for taking the time to read the article. I would love to hear your approach and tips on upgrading the node. &lt;br&gt;
HASH&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>node</category>
    </item>
    <item>
      <title>PM2 Cheat Sheet &amp; Process Management Guide</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Sun, 21 Jan 2024 21:24:51 +0000</pubDate>
      <link>https://dev.to/hash01/pm2-cheatsheet-3fb0</link>
      <guid>https://dev.to/hash01/pm2-cheatsheet-3fb0</guid>
      <description>&lt;p&gt;Hello friends,&lt;br&gt;
I've created another cheatsheet, it's for pm2, which is actually my personal notes like the other articles. It could be helpful for you too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PM2 (Process Manager 2)&lt;/strong&gt;. PM2 is a production process manager for Node.js applications that helps keep your apps alive, simplifies logging, and enables zero-downtime deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Process Management:&lt;/strong&gt; Easily start, stop, and restart applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cluster Mode:&lt;/strong&gt; Scale apps across all CPU cores without code changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Restart:&lt;/strong&gt; Automatically restarts apps on crash or system reboot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Monitoring:&lt;/strong&gt; Track CPU and Memory usage via CLI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log Management:&lt;/strong&gt; Consolidated log streaming and flushing.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;I personally utilize it primarily for managing processes and logging, allowing you to start, stop, and automatically restart Node.js processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  💻 Here's a list of commonly used PM2 commands along with examples:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Starting Applications
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Start a basic Node app&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 start app.js&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start Next.js with a name&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 start npm --name "app-name" -- start&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start and watch for changes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 start app.js --watch&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Monitoring &amp;amp; Status
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;List all processes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 ls&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Show app details&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 show &amp;lt;app-name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time Dashboard&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 monit&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;View Logs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 logs &amp;lt;app-name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Managing Life Cycle
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stop a process&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 stop &amp;lt;app-name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restart a process&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 restart &amp;lt;app-name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zero-Downtime Reload&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 reload &amp;lt;app-name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete from list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 delete &amp;lt;app-name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clear logs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 flush &amp;lt;app-name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Persistence (Server Reboots)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Save current process list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 save&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generate startup script&lt;/td&gt;
&lt;td&gt;&lt;code&gt;pm2 startup&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;These commands should cover most of the common tasks you need to perform when working with PM2. For more detailed information, you can always refer to the official PM2 documentation.&lt;/p&gt;




&lt;h2&gt;
  
  
  📺 Deployment Tutorials
&lt;/h2&gt;

&lt;p&gt;If you're deploying a &lt;strong&gt;Next.js&lt;/strong&gt; site from scratch on Ubuntu with NGINX, these guides are highly recommended:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=IwWQG6lEdQQ" rel="noopener noreferrer"&gt;How To Deploy NextJS With Nginx and PM2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=DbREUJNgxqw" rel="noopener noreferrer"&gt;Deploy NextJS From Scratch (Ubuntu/NGINX/PM2)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🔗 References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pm2.keymetrics.io/docs/usage/quick-start/" rel="noopener noreferrer"&gt;Official PM2 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Key differences between GraphQL and RESTful API</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Thu, 09 Nov 2023 20:42:28 +0000</pubDate>
      <link>https://dev.to/hash01/key-differences-between-graphql-and-restful-api-17o9</link>
      <guid>https://dev.to/hash01/key-differences-between-graphql-and-restful-api-17o9</guid>
      <description>&lt;p&gt;GraphQL and RESTful API are two popular approaches for building APIs, but they have distinct differences in architecture, data fetching, development speed, metadata and validation, and API endpoints.&lt;/p&gt;

&lt;p&gt;The main key differences between GraphQL and RESTful API are as follows:&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;: GraphQL is an application layer server-side technology that is used for executing queries with existing data. It follows a client-driven architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RESTful API&lt;/strong&gt;: REST (Representational State Transfer) is a software architectural style that defines a set of constraints for creating web services. It follows a server-driven architecture.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Data Fetching:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;: With GraphQL, the client can specify exactly the data it needs in a query, and the server responds with a JSON object that fulfills those requirements. This eliminates overfetching and underfetching of data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RESTful API&lt;/strong&gt;: In RESTful API, the client needs to access multiple endpoints to gather the required data. This can lead to overfetching, as the endpoints may return additional information that is not needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Development Speed:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;: The development speed in GraphQL is generally faster compared to RESTful API, as it provides a declarative way of fetching and updating data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RESTful API&lt;/strong&gt;: The development speed in RESTful API is slower compared to GraphQL, as it requires creating new APIs for different data requirements.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Metadata and Validation:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;: GraphQL uses metadata for query validation, which helps in ensuring the correctness of queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RESTful API&lt;/strong&gt;: RESTful API does not have machine-readable metadata cacheable, and query validation is not available.(There are some libraraies tried to solve this issue like &lt;a href="https://github.com/trpc/trpc" rel="noopener noreferrer"&gt;TRPC&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  API Endpoints:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;: GraphQL API endpoints are single, and the server determines the available resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RESTful API&lt;/strong&gt;: RESTful API endpoints are multiple, and the shape and size of the resource are determined by the server.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is there anything else you would like to include?&lt;/p&gt;

&lt;p&gt;Best &lt;br&gt;
Hash&lt;/p&gt;

&lt;p&gt;Read more: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.guru99.com/graphql-vs-rest-apis.html" rel="noopener noreferrer"&gt;https://www.guru99.com/graphql-vs-rest-apis.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.howtographql.com/basics/1-graphql-is-the-better-rest/" rel="noopener noreferrer"&gt;https://www.howtographql.com/basics/1-graphql-is-the-better-rest/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/compare/the-difference-between-graphql-and-rest/" rel="noopener noreferrer"&gt;https://aws.amazon.com/compare/the-difference-between-graphql-and-rest/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=x6r4IzofPVc" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=x6r4IzofPVc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>graphql</category>
      <category>rest</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Visual Regression testing with Playwright</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Fri, 06 Oct 2023 15:02:51 +0000</pubDate>
      <link>https://dev.to/hash01/visual-regression-testing-with-playwright-2137</link>
      <guid>https://dev.to/hash01/visual-regression-testing-with-playwright-2137</guid>
      <description>&lt;p&gt;Visual Regression Testing is a software testing technique used to identify and prevent unintended visual changes in a web application or user interface (UI). It helps ensure that the visual appearance of a website or application remains consistent across different versions or updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Visual Regression Testing typically works ?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;capturing a baseline or reference screenshot of the UI (expected)&lt;/li&gt;
&lt;li&gt;take second screenshot after changes to the code&lt;/li&gt;
&lt;li&gt;testing pixel by pixel or at higher level (based on tools)&lt;/li&gt;
&lt;li&gt;visual diff and report&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Visual Regression Testing is valuable for:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;visual consistency&lt;/li&gt;
&lt;li&gt;cross-browser and cross-device testing&lt;/li&gt;
&lt;li&gt;automated testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Which tool can be used for:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Applitools Eyes:&lt;/strong&gt;&lt;br&gt;
Popularity: High&lt;br&gt;
Year of Introduction: 2014&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Percy:&lt;/strong&gt;&lt;br&gt;
Popularity: High&lt;br&gt;
Year of Introduction: 2015&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cypress with Cypress Image Snapshot:&lt;/strong&gt;&lt;br&gt;
Popularity: High&lt;br&gt;
Year of Introduction: Cypress Image Snapshot is a plugin for Cypress.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Selenium with WebdriverIO:&lt;/strong&gt;&lt;br&gt;
Popularity: High&lt;br&gt;
Year of Introduction: Selenium is older (introduced in 2004), WebDriverCSS and WebdriverIO are plugins/extensions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Playwright with Playwright Test Runner:&lt;/strong&gt;&lt;br&gt;
Popularity: Growing&lt;br&gt;
Year of Introduction: Playwright introduced in 2019; Playwright Test Runner is a testing framework built on top.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An Visual Regression testing with React and Playwright
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install Playwright and other necessary dependencies:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a Visual Regression Testing script using Playwright and Jest. For this example, let's assume you want to test a simple React component.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a test file, e.g., visual-regression.test.js, with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Visual Regression Test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Navigate to your React application or component&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Change the URL as needed&lt;/span&gt;

  &lt;span class="c1"&gt;// Capture a screenshot of the React component&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;screenshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;screenshot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Compare the screenshot with the baseline image&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screenshot&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toMatchSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-component-screenshot.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;run the jest by &lt;code&gt;npm run test&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jest will execute the test script, and Playwright will launch a browser, capture a screenshot, and compare it to the baseline image. If there are any visual differences, Jest will report them.&lt;/p&gt;

&lt;p&gt;After running the test, Jest will generate a folder named &lt;strong&gt;image_snapshots&lt;/strong&gt; containing the baseline and compared images. You can review and approve any changes as needed.&lt;/p&gt;

&lt;p&gt;Remember to replace the URL and adjust the test script to match your specific React component or application. This example demonstrates a basic setup for Visual Regression Testing with Playwright and React, and you can expand upon it to suit your project's needs.&lt;/p&gt;

&lt;p&gt;if you would like to watch a video, there is another example: &lt;a href="https://www.youtube.com/watch?v=Y1eTK-j66PU" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=Y1eTK-j66PU&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for taking the time to read the article. let me know in the comments your approach to visual regression testing?&lt;/p&gt;

&lt;p&gt;HASH&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>testing</category>
      <category>playwright</category>
    </item>
    <item>
      <title>A Comparative Overview of Leading Web Servers: Nginx, Apache, LiteSpeed, and More</title>
      <dc:creator>Hamid Shoja</dc:creator>
      <pubDate>Sun, 01 Oct 2023 08:35:06 +0000</pubDate>
      <link>https://dev.to/hash01/a-comparative-overview-of-leading-web-servers-nginx-apache-litespeed-and-more-2omn</link>
      <guid>https://dev.to/hash01/a-comparative-overview-of-leading-web-servers-nginx-apache-litespeed-and-more-2omn</guid>
      <description>&lt;p&gt;In the ever-evolving landscape of web hosting and server technologies, picking the right web server can feel like choosing the perfect coffee blend—overwhelming at first, but crucial for your daily grind. Whether you're a seasoned sysadmin, a web developer, or just dipping your toes into the world of web hosting, this guide will help you navigate the options and find the ideal match for your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Popular Web Servers at a Glance
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Nginx
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creator:&lt;/strong&gt; Igor Sysoev&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; C&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popularity:&lt;/strong&gt; High&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notable Modules:&lt;/strong&gt; ngx_http_ssl_module (SSL/TLS support), ngx_http_proxy_module (HTTP proxy), ngx_http_fastcgi_module (FastCGI support)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Year Introduced:&lt;/strong&gt; 2004&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Famous Users:&lt;/strong&gt; Airbnb, Dropbox, Netflix, WordPress.com&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Apache HTTP Server (Apache)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creator:&lt;/strong&gt; Apache Software Foundation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; C&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popularity:&lt;/strong&gt; High&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notable Modules:&lt;/strong&gt; mod_ssl (SSL/TLS support), mod_rewrite (URL rewriting), mod_proxy (reverse proxy)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Year Introduced:&lt;/strong&gt; 1995&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Famous Users:&lt;/strong&gt; Apple, IBM, Cisco&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  HAProxy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creator:&lt;/strong&gt; Willy Tarreau&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; C&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popularity:&lt;/strong&gt; Medium&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notable Modules:&lt;/strong&gt; N/A (primarily a load balancer and proxy)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Year Introduced:&lt;/strong&gt; 2001&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Famous Users:&lt;/strong&gt; GitHub, Stack Overflow, Imgur&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Caddy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creator:&lt;/strong&gt; Matt Holt&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popularity:&lt;/strong&gt; Medium&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notable Modules:&lt;/strong&gt; tls.dns.cloudflare (DNS challenge provider for Let's Encrypt), http.expires (HTTP caching), http.proxy (HTTP proxy)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Year Introduced:&lt;/strong&gt; 2015 (Caddy 1.0), 2020 (Caddy 2.0)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Famous Users:&lt;/strong&gt; Segment, Atlassian, HashiCorp&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Traefik
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creator:&lt;/strong&gt; Containous&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; Go&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popularity:&lt;/strong&gt; Medium&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notable Modules:&lt;/strong&gt; acme (Let's Encrypt certificate automation), traefik-forward-auth (authentication middleware), consul (Service discovery)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Year Introduced:&lt;/strong&gt; 2014&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Famous Users:&lt;/strong&gt; SendGrid, Nokia, Ubisoft&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Envoy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creator:&lt;/strong&gt; Lyft&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; C++&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popularity:&lt;/strong&gt; Medium&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notable Modules:&lt;/strong&gt; N/A (primarily a proxy)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Year Introduced:&lt;/strong&gt; 2016&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Famous Users:&lt;/strong&gt; Airbnb, Pinterest, eBay&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tomcat
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Creator:&lt;/strong&gt; Apache Software Foundation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; Java&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popularity:&lt;/strong&gt; Medium&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notable Modules:&lt;/strong&gt; N/A (primarily a servlet container)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Year Introduced:&lt;/strong&gt; 1999&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Famous Users:&lt;/strong&gt; eBay, Adobe, LinkedIn&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Tips for Choosing a Web Server
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Matters:&lt;/strong&gt; Nginx and Apache are known for their high performance, but Nginx often edges out Apache in handling concurrent connections. If speed is your priority, Nginx might be your go-to.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of Use:&lt;/strong&gt; Caddy and Traefik are praised for their simplicity and automatic HTTPS setup. If you're looking for a hassle-free experience, these are worth considering.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; HAProxy and Envoy are excellent choices for load balancing and microservices architectures. They shine in environments where scalability is key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community Support:&lt;/strong&gt; Apache and Nginx have large, active communities, making it easier to find help and resources. If community support is important, these are solid picks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security:&lt;/strong&gt; All servers offer robust security features, but Nginx and Apache are particularly well-regarded for their security modules. Always keep your server updated and follow best practices.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Last word!
&lt;/h2&gt;

&lt;p&gt;Choosing the right web server is a blend of understanding your project's needs, evaluating performance, and considering ease of use. &lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;Hash!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;References:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nginx.org/en/docs/" rel="noopener noreferrer"&gt;Nginx Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://httpd.apache.org/docs/" rel="noopener noreferrer"&gt;Apache HTTP Server Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://caddyserver.com/docs/" rel="noopener noreferrer"&gt;Caddy Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.traefik.io/traefik/" rel="noopener noreferrer"&gt;Traefik Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.envoyproxy.io/docs/envoy/latest/" rel="noopener noreferrer"&gt;Envoy Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.haproxy.org/#docs" rel="noopener noreferrer"&gt;HAProxy Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tomcat.apache.org/tomcat-9.0-doc/" rel="noopener noreferrer"&gt;Tomcat Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
    </item>
  </channel>
</rss>
