<?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: Dyami Connell</title>
    <description>The latest articles on DEV Community by Dyami Connell (@dyami_connell).</description>
    <link>https://dev.to/dyami_connell</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%2F3677568%2F85d48cfc-8ecd-4034-8936-8283d1fb2227.png</url>
      <title>DEV Community: Dyami Connell</title>
      <link>https://dev.to/dyami_connell</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dyami_connell"/>
    <language>en</language>
    <item>
      <title>Hey: The Surprisingly Deep Art of Saying Hello in Software Systems</title>
      <dc:creator>Dyami Connell</dc:creator>
      <pubDate>Mon, 20 Apr 2026 04:03:23 +0000</pubDate>
      <link>https://dev.to/dyami_connell/hey-the-surprisingly-deep-art-of-saying-hello-in-software-systems-4jd6</link>
      <guid>https://dev.to/dyami_connell/hey-the-surprisingly-deep-art-of-saying-hello-in-software-systems-4jd6</guid>
      <description>&lt;p&gt;When was the last time you thought deeply about a greeting? In human conversation, "hey" is effortless — a throwaway syllable that opens a channel of communication. But in software systems, that simple act of saying hello is one of the most architecturally significant moments in any interaction. The humble greeting encapsulates authentication, protocol negotiation, state initialization, and connection management all at once.&lt;/p&gt;

&lt;p&gt;This article dives deep into the mechanics of "saying hello" in software — from TCP handshakes to API health checks, from WebSocket upgrades to distributed system heartbeats. By the end, you'll never look at a simple greeting the same way again.&lt;/p&gt;




&lt;h2&gt;
  
  
  The TCP Handshake: The Original "Hey"
&lt;/h2&gt;

&lt;p&gt;Before any web request, API call, or WebSocket message, two machines have to formally introduce themselves. This is the TCP three-way handshake — arguably the most important "hey" in all of computing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client                          Server
  |                               |
  |-------- SYN (Hey!) ---------&amp;gt;|
  |                               |
  |&amp;lt;------ SYN-ACK (Hey back!) --|
  |                               |
  |-------- ACK (Cool, let's talk)|
  |                               |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The process goes like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;SYN&lt;/strong&gt;: The client sends a synchronization packet. "Hey, I want to talk. Here's my initial sequence number."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SYN-ACK&lt;/strong&gt;: The server acknowledges and responds with its own sequence number. "Hey back! Got your number, here's mine."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACK&lt;/strong&gt;: The client acknowledges the server's sequence number. "Perfect. Let's communicate."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This seemingly simple exchange establishes something profound: a &lt;strong&gt;reliable, ordered, bidirectional channel&lt;/strong&gt;. Each side knows the other is alive, reachable, and ready.&lt;/p&gt;

&lt;p&gt;In modern TLS connections, this greeting becomes even more elaborate:&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;ssl&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;

&lt;span class="c1"&gt;# Python demonstrates the layers of "hello" involved in a secure connection
&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_default_context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_connection&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrap_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server_hostname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ssock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Protocol negotiated: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ssock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;version&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cipher suite chosen: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ssock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cipher&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Only NOW can we actually say hello at the application layer
&lt;/span&gt;        &lt;span class="n"&gt;ssock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendall&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;GET / HTTP/1.1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;Host: example.com&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the TCP handshake, TLS adds a &lt;strong&gt;ClientHello&lt;/strong&gt; and &lt;strong&gt;ServerHello&lt;/strong&gt; — yes, those are the actual names in the specification. Each hello carries capabilities, supported cipher suites, and certificates. The protocol was literally designed around the concept of greeting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Health Checks and Heartbeats: Saying "I'm Still Here"
&lt;/h2&gt;

&lt;p&gt;In distributed systems, the greeting doesn't happen just once. Systems need to continuously reassure each other that they're alive. This is where health checks and heartbeat mechanisms come in.&lt;/p&gt;

&lt;p&gt;A basic HTTP health check endpoint is one of the first things you should build into any service:&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="c1"&gt;// Express.js health check endpoint&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/health&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;healthData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&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="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;uptime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uptime&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&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;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&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;APP_VERSION&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;checkDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;checkCacheConnection&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;messageQueue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;checkQueueConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isHealthy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;healthData&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="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dep&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isHealthy&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="mi"&gt;503&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;span class="nx"&gt;healthData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Perform a lightweight query&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;latency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastQueryTime&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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;Kubernetes uses this concept extensively through &lt;strong&gt;liveness&lt;/strong&gt; and &lt;strong&gt;readiness probes&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service:latest&lt;/span&gt;
      &lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/health/live&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
        &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
        &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
      &lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/health/ready&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
        &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The distinction between liveness ("Am I alive?") and readiness ("Am I ready to receive traffic?") is a masterclass in nuanced greeting design. A service can be alive but not yet warmed up — just like a person who's awake but not ready to take your call.&lt;/p&gt;




&lt;h2&gt;
  
  
  WebSockets: The Greeting That Changes Everything
&lt;/h2&gt;

&lt;p&gt;HTTP is inherently a request-response protocol — it's like sending letters. WebSockets, on the other hand, open a persistent, bidirectional channel. But to get there, you first need a very special greeting: the &lt;strong&gt;WebSocket upgrade handshake&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/chat&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;server.example.com&lt;/span&gt;
&lt;span class="na"&gt;Upgrade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;websocket&lt;/span&gt;
&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt;
&lt;span class="na"&gt;Sec-WebSocket-Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dGhlIHNhbXBsZSBub25jZQ==&lt;/span&gt;
&lt;span class="na"&gt;Sec-WebSocket-Version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;13&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;101&lt;/span&gt; &lt;span class="ne"&gt;Switching Protocols&lt;/span&gt;
&lt;span class="na"&gt;Upgrade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;websocket&lt;/span&gt;
&lt;span class="na"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt;
&lt;span class="na"&gt;Sec-WebSocket-Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;s3pPLMBiTxaQ9kYGzzhZRbK+xOo=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server's &lt;code&gt;101 Switching Protocols&lt;/code&gt; response is one of the most dramatic status codes in HTTP — it literally says "the rules of our conversation are changing." That initial HTTP greeting bootstraps an entirely different protocol.&lt;/p&gt;

&lt;p&gt;Here's a practical implementation showing how to handle this gracefully:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WebSocketServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&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;ws&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IncomingMessage&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;http&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;wss&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;WebSocketServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;connectedAt&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="nl"&gt;lastHeartbeat&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Client&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;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connection&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="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&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="nx"&gt;IncomingMessage&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;clientId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;connectedAt&lt;/span&gt;&lt;span class="p"&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="na"&gt;lastHeartbeat&lt;/span&gt;&lt;span class="p"&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="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// The first message after "hey" - send the client their identity&lt;/span&gt;
  &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&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="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;WELCOME&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&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="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hey! Connection established successfully.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="c1"&gt;// Set up heartbeat&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;heartbeatInterval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&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;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ping&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="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pong&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastHeartbeat&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="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&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="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;heartbeatInterval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientId&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;`Client &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; said goodbye.`&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;Notice how even after the connection is established, we immediately send a &lt;code&gt;WELCOME&lt;/code&gt; message. This is an application-level hello layered on top of the protocol-level hello — greetings all the way down.&lt;/p&gt;




&lt;h2&gt;
  
  
  gRPC and Protocol Buffers: The Strongly-Typed Hello
&lt;/h2&gt;

&lt;p&gt;REST APIs say hello in plain, human-readable JSON. But gRPC takes a different approach — its greetings are strictly typed, compiled, and efficient. The canonical example in every gRPC tutorial is, fittingly, a greeting service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight protobuf"&gt;&lt;code&gt;&lt;span class="c1"&gt;// hello.proto&lt;/span&gt;
&lt;span class="na"&gt;syntax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"proto3"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;service&lt;/span&gt; &lt;span class="n"&gt;Greeter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Unary: simple hello&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;SayHello&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Server streaming: hello that keeps talking&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;SayHelloStream&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Bidirectional streaming: conversation&lt;/span&gt;
  &lt;span class="k"&gt;rpc&lt;/span&gt; &lt;span class="n"&gt;Chat&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;HelloRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="n"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;HelloRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;name&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="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;language&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="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="na"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;message&lt;/span&gt; &lt;span class="nc"&gt;HelloReply&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="kd"&gt;message&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="kt"&gt;string&lt;/span&gt; &lt;span class="na"&gt;server_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="kt"&gt;int64&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# gRPC server implementation
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hello_pb2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hello_pb2_grpc&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;concurrent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;futures&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreeterServicer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hello_pb2_grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GreeterServicer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;SayHello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;greetings&lt;/span&gt; &lt;span class="o"&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;en&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hey, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&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;es&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;¡Hola, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&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;fr&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Salut, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&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;de&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hallo, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&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="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;greetings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hey, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;'&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;hello_pb2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;server_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;server-001&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;SayHelloStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;hello_pb2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;HelloReply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hey &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, message &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; of 5&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;server_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;server-001&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;hello_pb2_grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_GreeterServicer_to_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;GreeterServicer&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_insecure_port&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[::]:50051&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gRPC server started — ready to say hey on port 50051&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_termination&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gRPC greeter is deliberately chosen as the "Hello World" of RPC frameworks because it perfectly encapsulates what the framework is for: establishing a typed, efficient, reliable communication channel between services.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Conclusion: Design Your Greetings Intentionally
&lt;/h2&gt;

&lt;p&gt;Every layer of your software stack has a concept of "hey" — and each one carries critical information and establishes important contracts. Here are the key takeaways to bring into your next project:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Make health checks meaningful, not ceremonial.&lt;/strong&gt;&lt;br&gt;
A &lt;code&gt;/health&lt;/code&gt; endpoint that just returns &lt;code&gt;200 OK&lt;/code&gt; is better than nothing, but an endpoint that validates your database connection, cache availability, and downstream dependencies is genuinely useful. Design your health checks to reflect real readiness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Never neglect the handshake.&lt;/strong&gt;&lt;br&gt;
Whether you're building a WebSocket server, a gRPC service, or a custom TCP protocol, invest time in the connection establishment phase. This is where you negotiate capabilities, authenticate clients, and set expectations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Heartbeats are mandatory in distributed systems.&lt;/strong&gt;&lt;br&gt;
Silence doesn't mean success — it might mean failure. Implement heartbeat mechanisms in any long-lived connection, and define what you'll do when a heartbeat is missed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Layer your hellos appropriately.&lt;/strong&gt;&lt;br&gt;
A TLS connection has a TCP hello, a TLS hello, and then an application-level hello. Don't try to collapse these — each layer serves a distinct purpose. Respect the separation of concerns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Your first message sets the tone.&lt;/strong&gt;&lt;br&gt;
When a WebSocket connection opens or a new gRPC stream begins, the first message you send should orient the client: their session ID, server capabilities, protocol version, and anything else they need to participate effectively.&lt;/p&gt;

&lt;p&gt;The next time you type "Hey" in a Slack message, take a moment to appreciate the dozens of protocol handshakes, heartbeats, and health checks that made that single word possible. In software, as in life, a good greeting is the foundation of everything that follows.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's your favorite "hello" in software? Drop a comment below — I'd love to hear about interesting connection protocols or handshake implementations you've encountered in the wild.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>distributedsystems</category>
      <category>networking</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Vibe Coding Is Genuinely Incredible (But Let's Talk About the Business Model Problem Too)</title>
      <dc:creator>Dyami Connell</dc:creator>
      <pubDate>Mon, 20 Apr 2026 03:57:51 +0000</pubDate>
      <link>https://dev.to/dyami_connell/vibe-coding-is-genuinely-incredible-but-lets-talk-about-the-business-model-problem-too-4hgn</link>
      <guid>https://dev.to/dyami_connell/vibe-coding-is-genuinely-incredible-but-lets-talk-about-the-business-model-problem-too-4hgn</guid>
      <description>&lt;p&gt;The future of software development has arrived, and it looks nothing like what we expected. Instead of meticulously typing every semicolon and debugging stack traces at 2am, a growing wave of developers — and even non-developers — are building real, functional, deployed applications by simply &lt;em&gt;describing&lt;/em&gt; what they want. This is vibe coding, and if you haven't tried it yet, your mind is about to be thoroughly blown.&lt;/p&gt;

&lt;p&gt;But here's the thing: as someone who has been deeply impressed by these tools, I also think we need to have an honest conversation about the business practices surrounding them. Because being a fan of the technology doesn't mean we should be uncritical cheerleaders for every decision these companies make. The best developer communities hold their tools accountable, and that's exactly what we're going to do today.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Even Is Vibe Coding?
&lt;/h2&gt;

&lt;p&gt;The term "vibe coding" was coined by Andrej Karpathy earlier in 2025 and it immediately resonated with a massive audience because it perfectly captures a real phenomenon. The idea is beautifully simple: you describe your application in natural language, the AI builds it, you iterate by describing what you want changed, and you largely ignore the underlying code. You go by the &lt;em&gt;vibe&lt;/em&gt; of what you're building.&lt;/p&gt;

&lt;p&gt;This sounds like heresy to classically trained engineers. But the results are genuinely hard to argue with.&lt;/p&gt;

&lt;p&gt;Tools like &lt;strong&gt;Lovable&lt;/strong&gt;, &lt;strong&gt;Bolt.new&lt;/strong&gt;, &lt;strong&gt;Cursor&lt;/strong&gt;, and &lt;strong&gt;v0 by Vercel&lt;/strong&gt; have made it possible to go from zero to a deployed, functional web application in under an hour without writing a single line of code yourself. For prototyping, for MVPs, for solo founders, for designers who want to test an idea — this is transformative.&lt;/p&gt;

&lt;p&gt;Here's a classic example of the kind of prompt that might generate an entire application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build me a full-stack task management app with:
- User authentication
- A dashboard showing tasks by priority
- The ability to assign due dates and tags
- A clean, minimal UI using shadcn components
- Supabase as the backend
Deploy it and give me the live URL.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That prompt, in Lovable, will genuinely produce something functional. Not a mockup. Not a wireframe. A real, deployed application with authentication, a database, and a live URL. That's wild. That's the technology we've always dreamed about.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Lovable Specifically Stands Out
&lt;/h2&gt;

&lt;p&gt;Let me be direct: Lovable (formerly GPT Engineer) is genuinely one of the most impressive pieces of software I have encountered in years of working in tech. The quality of the generated code, the way it handles multi-file projects, its understanding of modern React patterns, its Supabase integration, its ability to take screenshots and fix visual bugs — it's exceptional.&lt;/p&gt;

&lt;p&gt;The product experience of iterating on an application by just &lt;em&gt;talking&lt;/em&gt; to it is addictive. You find yourself thinking about problems differently. Instead of asking "how do I implement this?" you ask "what do I actually want this to do?" That cognitive shift is valuable even if you go back to writing code manually afterward.&lt;/p&gt;

&lt;p&gt;The generated code isn't garbage either. It produces typed TypeScript, follows component architecture patterns, uses proper hooks, and integrates with real services. Developers can actually look at what was generated and learn from it:&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;// Example of the kind of typed, structured code Lovable generates&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;low&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dueDate&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useTaskManager&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="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;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Task&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;addTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;newTask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&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="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="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;error&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;supabase&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tasks&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="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;newTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&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="nf"&gt;select&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="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&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;prev&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]]);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addTask&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;That's clean. That's readable. That's something a junior developer could extend and learn from. The tool is genuinely good, and I want to be clear about that before moving into criticism.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Credits Problem: When Deceptive Design Erodes Trust
&lt;/h2&gt;

&lt;p&gt;Now we need to talk about the part that genuinely angers me, because I think it's important and the developer community shouldn't just shrug it off.&lt;/p&gt;

&lt;p&gt;I lost &lt;strong&gt;$400 in credits&lt;/strong&gt; on Lovable. Not because I misused the platform. Not because I made a purchase mistake I understood at the time. Because the credits &lt;strong&gt;expired&lt;/strong&gt;, and the expiration policy was not communicated clearly, prominently, or repeatedly. By the time I noticed, the credits were simply gone.&lt;/p&gt;

&lt;p&gt;This is not a minor UX quibble. This is a pattern in SaaS pricing that has a name: &lt;strong&gt;dark patterns&lt;/strong&gt;. Specifically, this falls into the category of &lt;em&gt;hidden costs and terms&lt;/em&gt; — a design approach where the unfavorable conditions of a purchase are technically disclosed but buried, minimized, or otherwise obscured so that a normal, reasonable user would not notice them until it was too late.&lt;/p&gt;

&lt;p&gt;Let's think about this from a pure product ethics standpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ETHICAL CREDIT SYSTEM DESIGN:
✅ Expiration date shown prominently at purchase
✅ Remaining credits visible on every session
✅ Email warnings at 30 days, 7 days, 1 day before expiry
✅ In-app banner notifications as expiry approaches
✅ Option to extend or convert credits before loss
✅ Clear, plain-language terms in the checkout flow

WHAT ACTUALLY HAPPENED:
❌ Expiration buried in terms or fine print
❌ No prominent dashboard warning
❌ No proactive email sequence about expiring credits
❌ Credits silently vanished
❌ $400 gone with no recourse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frustrating irony is that this doesn't even make good business sense. Lovable is a genuinely excellent product. If someone spends $400 with you and has a great experience, they will almost certainly spend more. They will tell their developer friends. They will write articles like this one recommending the platform. But when you silently drain $400 from someone's account? You lose not just that customer's future spend, but their advocacy, their trust, and — yes — you turn what would have been a glowing recommendation into a mixed review with a warning label attached.&lt;/p&gt;

&lt;p&gt;Loyalty is earned. And you cannot earn loyalty through deception, even if it's technically legal deception buried in terms of service.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Vibe Coding Fits Into a Real Development Workflow
&lt;/h2&gt;

&lt;p&gt;Despite the frustration, I want to pivot back to something constructive, because vibe coding genuinely deserves a place in the modern developer's toolkit. The question isn't "should I use these tools?" — it's "where do they fit?"&lt;/p&gt;

&lt;p&gt;Here's how I've seen the most effective developers integrate vibe coding:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Rapid Prototyping and Validation&lt;/strong&gt;&lt;br&gt;
Before writing a single line of production code, spin up a vibe-coded prototype to validate the concept with real users. This can replace weeks of design and development with hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Boilerplate Elimination&lt;/strong&gt;&lt;br&gt;
Auth systems, CRUD interfaces, admin panels, landing pages — all of this can be vibe-coded and then refined by hand. Let the AI handle the scaffolding, let the engineer handle the differentiation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Learning by Reading Generated Code&lt;/strong&gt;&lt;br&gt;
For newer developers, vibe coding tools can be powerful learning accelerators. Generate a working example, then read through it and understand why each piece works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# A practical vibe coding workflow&lt;/span&gt;
1. Describe your full application concept to Lovable/Bolt
2. Get a deployed prototype &lt;span class="k"&gt;in &lt;/span&gt;under an hour
3. Download or connect to the GitHub repo
4. Review the generated code structure
5. Identify what needs custom logic vs what&lt;span class="s1"&gt;'s fine as-is
6. Hand-code only the truly differentiated pieces
7. Use the AI tool for continued iteration on standard features
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Solo Founders and Indie Hackers&lt;/strong&gt;&lt;br&gt;
If you're building alone, vibe coding can effectively give you the output of a small team for the standard, repeatable parts of your application. This is a genuine competitive advantage for early-stage products.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We Should Demand From AI Development Tools
&lt;/h2&gt;

&lt;p&gt;The technology is exciting. The business practices sometimes aren't. As a developer community, we have both the voice and the leverage to push back. Here's what fair, developer-respecting AI tools should look like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Transparent pricing with zero hidden gotchas.&lt;/strong&gt; If credits expire, that should be impossible to miss at the point of purchase and throughout usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proactive communication about usage and limits.&lt;/strong&gt; We should never discover something has expired. We should be warned aggressively before it happens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credit extensions or rollover policies.&lt;/strong&gt; Unused credits that vanish are a consumer trust killer. Offer to roll them over, apply them to a subscription, or at minimum give significant notice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive support for pricing disputes.&lt;/strong&gt; When a customer comes to you having lost significant money due to unclear terms, treating them well costs you almost nothing and retains a customer. Treating them poorly is a PR disaster in slow motion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best developer tools win long-term through genuine product quality and community trust — not through extracting maximum value from confusion. Stripe, Vercel, Supabase, GitHub — the developer tools that have achieved true loyalty did so by being transparent, generous, and developer-first in their thinking.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Vibe Coding Is the Future, But We Deserve Better Business Practices
&lt;/h2&gt;

&lt;p&gt;Here's where I land after all of this: vibe coding is real, it's impressive, and it's going to fundamentally change who can build software and how fast they can build it. Lovable is one of the best implementations of this technology available today, and the core product genuinely deserves the excitement it has generated in the community.&lt;/p&gt;

&lt;p&gt;And also: losing $400 to unexplained, unexpired, silently disappearing credits is not okay. Both things are true at the same time.&lt;/p&gt;

&lt;p&gt;We should enthusiastically adopt tools that make us more productive. We should recommend tools that genuinely impress us. And we should be loud and clear when the business practices of those tools fall short of what we deserve as paying customers. The two are not in conflict.&lt;/p&gt;

&lt;p&gt;If you're going to try Lovable or any similar platform — and you absolutely should — go in with eyes open. Read the credit terms carefully. Set your own calendar reminders for when credits expire. Screenshot your purchase confirmation. Don't rely on the platform to protect you from losing money, because as I learned the hard way, that protection may not be there.&lt;/p&gt;

&lt;p&gt;Build cool things. Use incredible tools. And demand that the companies behind those tools treat you with the same respect you bring to your craft.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you had experiences — good or bad — with vibe coding platforms? Drop them in the comments. The more we share transparently, the better informed our community becomes.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>softwaredevelopment</category>
      <category>vibecoding</category>
    </item>
    <item>
      <title>Vibe Coding: A Workflow Guide (From Zero to SaaS)</title>
      <dc:creator>Dyami Connell</dc:creator>
      <pubDate>Sat, 18 Apr 2026 19:11:22 +0000</pubDate>
      <link>https://dev.to/dyami_connell/vibe-coding-a-workflow-guide-from-zero-to-saas-4h6l</link>
      <guid>https://dev.to/dyami_connell/vibe-coding-a-workflow-guide-from-zero-to-saas-4h6l</guid>
      <description>&lt;p&gt;A few months ago, I had zero coding skills and zero dollars from my own online project. Today, I've crossed the $1,000 mark with my side project &lt;a href="https://protooltrack.com" rel="noopener noreferrer"&gt;protooltrack.com&lt;/a&gt; — and I owe almost all of it to &lt;strong&gt;vibe coding&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you haven't heard the term yet, vibe coding is the practice of building software by describing what you want in plain English to an AI assistant, iterating on the output, and shipping fast — without needing to master every line of code yourself. It's messy, it's fun, and apparently it works.&lt;/p&gt;

&lt;p&gt;Here's the full story.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Idea: ProToolTrack
&lt;/h2&gt;

&lt;p&gt;I work in construction, and one problem I kept running into was tracking expensive power tools. Who has the drill? Where's the laser level? When does that compressor need servicing? Spreadsheets were a nightmare, and the existing apps felt like overkill.&lt;/p&gt;

&lt;p&gt;So I thought: &lt;em&gt;what if there was a simple, no-fuss tool tracking app for small contractors and tradespeople?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That became &lt;strong&gt;ProToolTrack&lt;/strong&gt; — a web app where you can log your tools, assign them to team members, and get reminders when maintenance is due.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Build: Pure Vibe Coding
&lt;/h2&gt;

&lt;p&gt;I had dabbled in HTML back in the day, but I couldn't have built a full-stack web app on my own. So I leaned entirely into AI-assisted development.&lt;/p&gt;

&lt;p&gt;My workflow looked like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Describe the feature, get the code&lt;/strong&gt;&lt;br&gt;
I'd open up an AI coding assistant and literally say things like: &lt;em&gt;"Build me a form where a user can add a tool with a name, serial number, category, and assigned team member."&lt;/em&gt; It would spit out React components, database schema suggestions, API routes — the works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Paste, run, break, fix&lt;/strong&gt;&lt;br&gt;
I'd paste the code, run it, inevitably hit an error, paste the error back into the AI, and get a fix. Rinse and repeat. It felt more like conducting than coding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Ship early, iterate fast&lt;/strong&gt;&lt;br&gt;
I launched with just three features: add a tool, assign it to someone, and mark it as returned. That was it. No fancy dashboard, no analytics, just a working MVP.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting to $1,000
&lt;/h2&gt;

&lt;p&gt;The money didn't come overnight. Here's how it broke down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Month 1 — $0:&lt;/strong&gt; I launched quietly and shared the project in a few subreddits (r/Entrepreneur and r/SideProject). Got some encouraging feedback but no paying customers yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Month 2 — $147:&lt;/strong&gt; I added a simple $9/month subscription tier and announced it to the small email list I'd built. A handful of early supporters signed up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Month 3 — $389:&lt;/strong&gt; Word started spreading in a Facebook group for small contractors. A few guys tried it, liked it, and told their crews.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Month 4 — $464 more:&lt;/strong&gt; By month four, I crossed the $1,000 total mark. Nothing viral, just steady growth from people genuinely finding it useful.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What Vibe Coding Actually Feels Like
&lt;/h2&gt;

&lt;p&gt;Honestly? It's humbling and exciting at the same time.&lt;/p&gt;

&lt;p&gt;There were moments where I had no idea &lt;em&gt;why&lt;/em&gt; a piece of code worked — I just knew it did. That felt weird at first. But I got over it. A contractor doesn't need to understand the metallurgy of their drill bits; they need to know how to build a deck.&lt;/p&gt;

&lt;p&gt;The real skill with vibe coding isn't writing prompts — it's &lt;strong&gt;judgment&lt;/strong&gt;. Knowing when the AI is steering you wrong, when to push back, when to ask for a simpler solution, and when to just ship the thing.&lt;/p&gt;

&lt;p&gt;Some lessons I picked up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start with the simplest possible version.&lt;/strong&gt; The AI will suggest features you don't need. Resist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep your prompts focused.&lt;/strong&gt; One feature at a time. Vague prompts produce vague code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't skip testing.&lt;/strong&gt; Use the app yourself, daily. You'll find bugs faster than any automated test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Talk to users early.&lt;/strong&gt; Real feedback beats imagined features every time.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The $1,000 Is Just the Beginning
&lt;/h2&gt;

&lt;p&gt;I'm not going to pretend $1,000 is life-changing money. But it validated something important: a real problem, a real product, real people paying for it.&lt;/p&gt;

&lt;p&gt;I'm now working on a mobile-friendly version, team dashboards, and barcode scanning for quick tool check-in/check-out. All vibe coded, of course.&lt;/p&gt;

&lt;p&gt;If you're sitting on an idea and waiting until you "know how to code" — stop waiting. The tools are here. The barrier is lower than it's ever been.&lt;/p&gt;

&lt;p&gt;Just start vibing.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you tried vibe coding for your own projects? I'd love to hear your experience in the comments. And if you're in the trades and want to try ProToolTrack, check it out at &lt;a href="https://protooltrack.com" rel="noopener noreferrer"&gt;protooltrack.com&lt;/a&gt; — there's a free tier to get you started.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>entrepreneurship</category>
      <category>ai</category>
      <category>showdev</category>
    </item>
    <item>
      <title>How I Built a Custom Search Engine for Browning Motor Sheaves</title>
      <dc:creator>Dyami Connell</dc:creator>
      <pubDate>Fri, 16 Jan 2026 18:38:02 +0000</pubDate>
      <link>https://dev.to/dyami_connell/how-i-built-a-custom-search-engine-for-browning-motor-sheaves-2ej6</link>
      <guid>https://dev.to/dyami_connell/how-i-built-a-custom-search-engine-for-browning-motor-sheaves-2ej6</guid>
      <description>&lt;p&gt;The Problem&lt;br&gt;
I work in HVAC Test &amp;amp; Balance (TAB). A big part of the job is identifying specific pulleys (sheaves) on rooftop units to adjust fan speeds.&lt;/p&gt;

&lt;p&gt;The old way involved carrying a physical catalog, measuring the part with calipers, and then manually flipping through pages to find a match. If the measurement was slightly off, or the catalog was missing a page, you were stuck guessing.&lt;/p&gt;

&lt;p&gt;I realized I could speed this up significantly if I just had a digital database I could search from my phone.&lt;/p&gt;

&lt;p&gt;The Build: The "Browning" Engine&lt;br&gt;
I built &lt;a href="https://testandbalance.xyz/" rel="noopener noreferrer"&gt;TestAndBalance.xyz&lt;/a&gt;, a simple web app that replaces the catalog.&lt;/p&gt;

&lt;p&gt;Here’s how I broke it down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Database: I needed the data first. I digitized the specs for over 2,000 Browning sheaves, mapping the physical dimensions (Outside Diameter, Pitch) to the actual Part Numbers and Bore sizes. Now, instead of a book, I have a queryable dataset.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Search Logic: Field measurements are rarely perfect. A sheave might be rusted, or the angle might be awkward. I set up the search to handle a bit of variance.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If I input 3.4, the logic searches a range (like 3.35 to 3.45) to find the closest valid part number. It acts as a "fuzzy search" for hardware.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Hardware Interface (Calipers) Since this tool relies on physical inputs, I still need to carry calipers. The software is only as good as the measurement I type in. It helps confirm I'm looking at a "3V" belt profile vs an "A" profile, which is hard to tell by eye but obvious when you measure it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Physics Layer&lt;br&gt;
To make it more than just a lookup tool, I added the Fan Laws (fluid dynamics formulas) into the frontend.&lt;/p&gt;

&lt;p&gt;When I select a new sheave size, the app automatically calculates the resulting Brake Horsepower (BHP). Since power increases with the cube of speed, a small change can ramp up power usage fast. The app flags the new BHP so I can verify it’s safe for the motor before I even order the part.&lt;/p&gt;

&lt;p&gt;Summary&lt;br&gt;
I built this because I wanted a tool that fit my specific workflow. It’s a PWA, so it loads instantly on a job site, and it saves me a few hours of manual lookup time every week.&lt;/p&gt;

&lt;p&gt;If you’re interested in automation for the trades or just want to see how it works, you can check it out here: &lt;a href="https://testandbalance.xyz/" rel="noopener noreferrer"&gt;TestAndBalance.xyz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m Dyami Connell, an HVAC TAB Technician.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Hacking the Trades: Why I Chose Python for HVAC Field Automation</title>
      <dc:creator>Dyami Connell</dc:creator>
      <pubDate>Thu, 01 Jan 2026 04:02:03 +0000</pubDate>
      <link>https://dev.to/dyami_connell/hacking-the-trades-why-i-chose-python-for-hvac-field-automation-1il4</link>
      <guid>https://dev.to/dyami_connell/hacking-the-trades-why-i-chose-python-for-hvac-field-automation-1il4</guid>
      <description>&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%2F7nb1ifv2mxzbts8z4h65.jpg" 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%2F7nb1ifv2mxzbts8z4h65.jpg" alt="Dyami-Connell-HVAC-Automation" width="800" height="1200"&gt;&lt;/a&gt;By Dyami Connell&lt;/p&gt;

&lt;p&gt;I recently wrote a breakdown of how I built the frontend interface of my tools using JavaScript (you can read that on my Dev.to profile here: [LINK TO YOUR DEV POST]).&lt;/p&gt;

&lt;p&gt;But today, I want to talk about the backend—the heavy lifting.&lt;/p&gt;

&lt;p&gt;As a TAB (Testing, Adjusting, and Balancing) Technician, the math I deal with isn't just "A + B." It involves fluid dynamics, fan laws, and air density corrections that change based on altitude and temperature.&lt;/p&gt;

&lt;p&gt;While JavaScript handles the web interface, I turned to Python to handle the actual engineering logic.&lt;/p&gt;

&lt;p&gt;The Problem: The "Bay Area" Factor Here in San Francisco, we deal with microclimates. One job site is at sea level; another is in the hills. Standard calculators often ignore Air Density ratios, which can throw a balance report off by 5-10%.&lt;/p&gt;

&lt;p&gt;The Python Solution I built a simple Python library for TestAndBalance.xyz that standardizes these corrections.&lt;/p&gt;

&lt;p&gt;Fan Laws: It iterates RPM/BHP changes instantly.&lt;/p&gt;

&lt;p&gt;Data Handling: Python allows me to eventually pump this data into Excel or PDF reports using libraries like pandas (something I'm working on now).&lt;/p&gt;

&lt;p&gt;Why Open Source Matters for Trades Most HVAC software is proprietary and expensive. I believe the basic math of our trade should be free. By using open-source languages like Python and JS, we can build tools that are accessible to every apprentice and journeyman in the field.&lt;/p&gt;

&lt;p&gt;Check out the tools live at TestAndBalance.xyz or view my full portfolio at dyamiconnell.com.&lt;br&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%2Fub011pdq9mpu1e9agrii.jpg" 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%2Fub011pdq9mpu1e9agrii.jpg" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>automation</category>
    </item>
    <item>
      <title>How I Automated HVAC Field Calculations with JavaScript (No more paper)</title>
      <dc:creator>Dyami Connell</dc:creator>
      <pubDate>Thu, 25 Dec 2025 00:54:06 +0000</pubDate>
      <link>https://dev.to/dyami_connell/how-i-automated-hvac-field-calculations-with-javascript-no-more-paper-2l1h</link>
      <guid>https://dev.to/dyami_connell/how-i-automated-hvac-field-calculations-with-javascript-no-more-paper-2l1h</guid>
      <description>&lt;p&gt;I work as a TAB (Testing, Adjusting, and Balancing) Technician in the HVAC industry.&lt;/p&gt;

&lt;p&gt;One of the biggest pain points in the field is doing repetitive math for duct traverses while standing on a ladder. The standard industry formulas (NEBB/AABC) aren't complicated, but doing them on a phone calculator leads to human error.&lt;/p&gt;

&lt;p&gt;The Problem Existing apps are either expensive, require a login (impossible in dead zones), or are filled with ads.&lt;/p&gt;

&lt;p&gt;The Solution I decided to build my own lightweight tool using React. It's a simple PWA (Progressive Web App) that handles:&lt;/p&gt;

&lt;p&gt;Round Duct Traverses (Log-Tchebycheff method)&lt;/p&gt;

&lt;p&gt;Rectangular Duct Grids&lt;/p&gt;

&lt;p&gt;Zero data collection&lt;/p&gt;

&lt;p&gt;The Stack&lt;/p&gt;

&lt;p&gt;Frontend: React&lt;/p&gt;

&lt;p&gt;Hosting: Netlify/Lovable&lt;/p&gt;

&lt;p&gt;Logic: Custom JS for the fluid dynamics formulas.&lt;/p&gt;

&lt;p&gt;You can try the live demo here: &lt;a href="https://dev.tourl"&gt;TestAndBalance.xyz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm currently working on a Python script to take these inputs and auto-generate the PDF reports we send to clients.&lt;/p&gt;

&lt;p&gt;If you are in th&lt;a href="https://dev.tourl"&gt;&lt;/a&gt;e trades and interested in how automation can help field work, check out my other projects at &lt;a href="https://dev.tourl"&gt;DyamiConnell.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>python</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
