<?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: Dev Rajput</title>
    <description>The latest articles on DEV Community by Dev Rajput (@dev_rajput_2d46f92f8a3418).</description>
    <link>https://dev.to/dev_rajput_2d46f92f8a3418</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3871240%2Fe734eb98-46c3-4cea-b6da-29e0680a10f8.jpg</url>
      <title>DEV Community: Dev Rajput</title>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dev_rajput_2d46f92f8a3418"/>
    <language>en</language>
    <item>
      <title>Soul in Motion — 5:28 PM | 2026-09-21</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Mon, 21 Sep 2026 12:21:27 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-528-pm-2026-09-21-1pjk</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-528-pm-2026-09-21-1pjk</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Refactored the &lt;strong&gt;Soul in Motion&lt;/strong&gt; site’s color scheme and added subtle text motion inspired by a peer’s design.&lt;/li&gt;
&lt;li&gt;Tackled a personal celestial distance visualizer, resolving cascading bugs from interactive elements.&lt;/li&gt;
&lt;li&gt;Cleaned up the local filesystem, clearing orphaned folders and gaining mental clarity.&lt;/li&gt;
&lt;li&gt;Drawn design inspiration from bold, unconventional sites and &lt;em&gt;Under the Banner of Heaven&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Ended the day with progress on both the company site and the side project, feeling satisfied with incremental wins.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Morning: Ripping Apart the Soul in Motion Palette
&lt;/h2&gt;

&lt;p&gt;I started the day staring at the black‑and‑red combo that had been stuck on the &lt;strong&gt;Soul in Motion&lt;/strong&gt; homepage for months. The gut feeling was that it was &lt;em&gt;stale&lt;/em&gt;—not just a color clash but a visual dead‑weight. Instead of a quick palette swap, I decided to inject &lt;strong&gt;motion&lt;/strong&gt; into the text itself, giving the page a subtle personality.&lt;/p&gt;

&lt;p&gt;I pulled up a screenshot from a recent design review that highlighted an older layout. My goal was to make sure the new motion didn’t just look good in isolation but actually &lt;em&gt;fit&lt;/em&gt; with the rest of the UI. The tension between “this looks striking” and “this is usable” is a constant in front‑end work, and I kept circling back to that balance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation Snapshot
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Simple keyframes for subtle horizontal text motion */&lt;/span&gt;
&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;slide&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%,&lt;/span&gt; &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5px&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="nc"&gt;.text-move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;slide&lt;/span&gt; &lt;span class="m"&gt;4s&lt;/span&gt; &lt;span class="n"&gt;ease-in-out&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wrapped the headline text in a &lt;code&gt;div.text-move&lt;/code&gt; and tweaked the timing until it felt natural. The result is a gentle, almost imperceptible glide that adds life without distracting from the content.&lt;/p&gt;




&lt;h2&gt;
  
  
  Afternoon: Debugging the Celestial Distance Visualizer
&lt;/h2&gt;

&lt;p&gt;The side project was a visualization of distances between celestial bodies. The goal was to make the data &lt;em&gt;intuitive&lt;/em&gt;, not a wall of numbers. Unfortunately, adding a tiny interactive element broke three others. A ghost of a removed element lingered, and a quiet button caused chaos downstream.&lt;/p&gt;

&lt;p&gt;I spent the afternoon chasing these cascading bugs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ghost Element&lt;/strong&gt; – A hidden &lt;code&gt;div&lt;/code&gt; still existed in the DOM, causing layout shifts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Button Cascade&lt;/strong&gt; – Clicking the “Show Details” button triggered a re‑render that inadvertently reset the entire state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Sync&lt;/strong&gt; – The new slider was not debounced, leading to rapid state changes that overloaded the rendering loop.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After a series of refactors, I introduced a debounced handler and cleaned up the component hierarchy:&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;// debounce.js&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;debounce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wait&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;let&lt;/span&gt; &lt;span class="nx"&gt;timeout&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;args&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;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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;func&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="kc"&gt;null&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="nx"&gt;wait&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// distance-visualizer.js&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;debounce&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;./debounce&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;handleSliderChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;updateDistances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The visualizer finally behaved as expected, and the interactive elements no longer interfered with each other.&lt;/p&gt;




&lt;h2&gt;
  
  
  Inspiration Hunt
&lt;/h2&gt;

&lt;p&gt;While the code was running, I opened a few sites known for bold, unconventional design—think &lt;em&gt;Awwwards&lt;/em&gt; winners and experimental UI showcases. I took mental notes on layout tricks and motion details that could be adapted for the company site later.&lt;/p&gt;

&lt;p&gt;I also let &lt;em&gt;Under the Banner of Heaven&lt;/em&gt; play in the background. The vivid scenes made me pause and question the intentionality of my own work. It’s a reminder that design is as much about narrative as it is about pixels.&lt;/p&gt;




&lt;h2&gt;
  
  
  File System Clean‑Up
&lt;/h2&gt;

&lt;p&gt;A small but surprisingly satisfying task: I hunted through my hard drive for folders that had stopped showing up where they should, cleared out the junk, and felt a wave of relief. Not every win needs to be complicated, but a tidy workspace can boost productivity and reduce cognitive load.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrap‑Up
&lt;/h2&gt;

&lt;p&gt;By the end of the day, I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A redesigned homepage with subtle text motion.&lt;/li&gt;
&lt;li&gt;A stubborn side project finally behaving.&lt;/li&gt;
&lt;li&gt;A cleaner hard drive.&lt;/li&gt;
&lt;li&gt;A head full of borrowed inspiration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both the company site and the distance visualizer are closer to completion than they were this morning. That, for me, is enough.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stay tuned for the next update.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>css</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Soul in Motion — 6:17 PM | 2026-09-18</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Fri, 18 Sep 2026 13:12:13 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-617-pm-2026-09-18-2fnc</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-617-pm-2026-09-18-2fnc</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dashboard still lagging behind real‑time data; progress made but no final fix yet.&lt;/li&gt;
&lt;li&gt;Re‑installed unnecessary components to isolate a stale cache issue.&lt;/li&gt;
&lt;li&gt;Voice‑recognition for Soulvoice improved; false positives reduced by tightening keyword spotting.&lt;/li&gt;
&lt;li&gt;Developed a structured play parser that correctly tokenizes lines and preserves character voices.&lt;/li&gt;
&lt;li&gt;Small wins across the day; no single breakthrough, but cumulative progress.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Day in the Life of a Builder – September 4
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Dashboard Dilemma
&lt;/h3&gt;

&lt;p&gt;The dashboard was supposed to surface real‑time metrics, but it kept showing yesterday’s numbers. I started by inspecting the data pipeline:&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;# Check the cache expiration header&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://api.myapp.com/metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The header returned &lt;code&gt;Cache-Control: max-age=86400&lt;/code&gt;, which explains why the data was stale. I removed the caching middleware from the Express route:&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;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;/metrics&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="c1"&gt;// Previously: res.set('Cache-Control', 'max-age=86400');&lt;/span&gt;
  &lt;span class="c1"&gt;// Now: no caching header&lt;/span&gt;
  &lt;span class="nf"&gt;fetchMetrics&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;json&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, I re‑installed the &lt;code&gt;node-cache&lt;/code&gt; package, which had been flagged as “unnecessary” in the &lt;code&gt;package.json&lt;/code&gt;. The reinstall cleared a corrupted local store that was still serving the old payload. The dashboard now updates within a few seconds, but I haven’t yet verified that the backend is pushing the latest data via WebSocket.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recurring Bug in the Feature Toggle Service
&lt;/h3&gt;

&lt;p&gt;Midday, a bug I thought I’d fixed in the feature toggle service resurfaced. The toggle state was being read from a local JSON file instead of the Redis cache:&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="c1"&gt;# toggle_service.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Previously: return local_toggles[name]
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;redis_client&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;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added a log statement to confirm the source:&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="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&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;Toggle &lt;/span&gt;&lt;span class="si"&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; fetched from &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;source&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The logs revealed that the fallback to the local file was still active when Redis returned &lt;code&gt;None&lt;/code&gt;. I updated the fallback logic:&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;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;is&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;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;local_toggles&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the service consistently reads from Redis, but the root cause—an uninitialized Redis key—remains to be addressed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voice Recognition Tweaks for Soulvoice
&lt;/h3&gt;

&lt;p&gt;The voice assistant’s wake‑word detection had a high false‑positive rate. I tightened the sensitivity threshold in the keyword spotting model:&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="c1"&gt;# config.yaml&lt;/span&gt;
&lt;span class="na"&gt;wake_word&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sensitivity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.75&lt;/span&gt;  &lt;span class="c1"&gt;# increased from 0.6&lt;/span&gt;
  &lt;span class="na"&gt;model_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/models/wake_word.bin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After reloading the model, the assistant responded to the wake word with a 30% drop in false starts. I also added a short silence buffer before accepting a command:&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;audioProcessor&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;speechEnd&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;silenceDuration&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;processCommand&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;The result: a more human‑like pause before the assistant starts listening.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structured Play Parser
&lt;/h3&gt;

&lt;p&gt;The highlight of the day was finally getting a parser that understands the structure of Shakespearean plays. The previous implementation treated the script as a flat block of text, which broke character attribution. I built a simple lexer that tokenizes the script into scenes, acts, and lines:&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;re&lt;/span&gt;

&lt;span class="n"&gt;SCENE_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^\s*Scene\s+\d+&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MULTILINE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ACT_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^\s*Act\s+\w+&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MULTILINE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;LINE_RE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^\s*(\w+):\s*(.+)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MULTILINE&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;parse_script&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;acts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ACT_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;act&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;acts&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="n"&gt;scenes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SCENE_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;act&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;scene&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scenes&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="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LINE_RE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;act&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;act&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;scene&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lines&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;lines&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;parsed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running this on &lt;em&gt;Macbeth&lt;/em&gt;, &lt;em&gt;Othello&lt;/em&gt;, and &lt;em&gt;Hamlet&lt;/em&gt; produced a structured JSON where each line is paired with its speaker. Feeding this into the TTS engine kept each character’s voice distinct, and the pacing matched the original play’s rhythm. The first test run—narrating &lt;em&gt;Hamlet&lt;/em&gt;—went through without a single misattributed line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Breaks and Side‑Projects
&lt;/h3&gt;

&lt;p&gt;I let the day wind down with a few AI‑and‑coding rabbit holes that started with a single search for “transformer fine‑tuning” and ended up exploring a new open‑source dataset for voice cloning. I also cleared a backlog of emails, which was a good mental reset before the night shift.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflections
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard&lt;/strong&gt;: Still not fully fixed; the real-time push mechanism needs a final tweak.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recurring bug&lt;/strong&gt;: Diagnosed, but the underlying Redis key issue is pending.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Soulvoice&lt;/strong&gt;: Wake‑word detection is noticeably more reliable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Play parser&lt;/strong&gt;: Works on the first real test; feels like a quiet triumph.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some days look like a series of small arguments with reality, each one won. Fingers crossed the rest sorts itself out before the next release. Stay tuned.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Soul in Motion — 6:16 PM | 2026-09-17</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Thu, 17 Sep 2026 13:07:58 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-616-pm-2026-09-17-2m1i</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-616-pm-2026-09-17-2m1i</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built an interactive &lt;em&gt;Frankenstein&lt;/em&gt; demo that animates scenes based on the text, including subtle air‑visualization.&lt;/li&gt;
&lt;li&gt;Expanded the concept into a shelf‑level platform, deploying a 10‑chapter book with scene sequencing and mood‑based weather.&lt;/li&gt;
&lt;li&gt;Tackled plumbing: data ingestion, scene orchestration, and secure hosting on a cloud platform.&lt;/li&gt;
&lt;li&gt;Parallel work: concise product explanations, Kathaverse short‑story scaffolding, comic frame transitions, and personal media breaks.&lt;/li&gt;
&lt;li&gt;All projects progressed incrementally; each small fix added realism and cohesion.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  From Page to Space: Making &lt;em&gt;Frankenstein&lt;/em&gt; Breathable
&lt;/h2&gt;

&lt;p&gt;The core idea was simple: turn a static text into a living environment.&lt;br&gt;&lt;br&gt;
I started with a &lt;strong&gt;react‑three-fiber&lt;/strong&gt; scene that loads the book’s JSON representation, then maps each chapter to a &lt;code&gt;Scene&lt;/code&gt; component. The component adjusts lighting, background audio, and particle effects based on metadata extracted from the text (e.g., “dark, stormy night”).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;chapter&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;mood&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;weather&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseMetadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chapter&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ambientLight&lt;/span&gt; &lt;span class="na"&gt;intensity&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mood&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;audio&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;weatherAudio&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AirParticles&lt;/span&gt; &lt;span class="na"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;chapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;air&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Invisible Air Effect
&lt;/h3&gt;

&lt;p&gt;The “air becomes visible” trick was a debugging win. I added a low‑opacity &lt;strong&gt;cloud&lt;/strong&gt; particle system that only activates when the text mentions “air” or “wind.” It’s almost imperceptible, but it grounds the reader in the environment.&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;function&lt;/span&gt; &lt;span class="nf"&gt;AirParticles&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="p"&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;points&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;bufferGeometry&lt;/span&gt; &lt;span class="nx"&gt;attach&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;geometry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;cloudGeometry&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;pointsMaterial&lt;/span&gt; &lt;span class="nx"&gt;attach&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;material&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;opacity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;transparent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/points&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The challenge was keeping the particles from over‑rendering. I throttled updates to once per second and used GPU instancing to keep the frame rate above 60 fps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scaling Up: From One Book to a Shelf
&lt;/h2&gt;

&lt;p&gt;After polishing the single‑book demo, I built a &lt;strong&gt;shelf&lt;/strong&gt; abstraction. Each book is a &lt;code&gt;ShelfItem&lt;/code&gt; that holds its own scene graph, metadata, and a small REST API for fetching the next chapter.&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="c1"&gt;# shelf.yaml&lt;/span&gt;
&lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frankenstein&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Frankenstein"&lt;/span&gt;
    &lt;span class="na"&gt;chapters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/books/frankenstein/chapters/1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;great_expectations&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Great&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Expectations"&lt;/span&gt;
    &lt;span class="na"&gt;chapters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/books/great_expectations/chapters/1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API is a lightweight Node/Express server that serves chapter JSON and a WebSocket for real‑time updates (e.g., when a user marks a bookmark).&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&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;app&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;WebSocket&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;ws&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="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;server&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="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;/books/:id/chapters/:num&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="nx"&gt;res&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="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`./data/&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;params&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="s2"&gt;/chapter&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;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&lt;/span&gt;&lt;span class="p"&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="nx"&gt;ws&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;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;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&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;// broadcast bookmark updates&lt;/span&gt;
    &lt;span class="nx"&gt;wss&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;forEach&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="nx"&gt;client&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;msg&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;h3&gt;
  
  
  Deployment Pipeline
&lt;/h3&gt;

&lt;p&gt;I containerized the stack with Docker and pushed it to a &lt;strong&gt;DigitalOcean App Platform&lt;/strong&gt; instance. The pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;docker build -t mybooks:latest .&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker push registry.digitalocean.com/myorg/mybooks:latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Deploy via the DO dashboard, exposing port 80.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The only real plumbing hurdle was ensuring the WebSocket endpoint survived the platform’s HTTP load balancer. I added a &lt;code&gt;proxy_pass&lt;/code&gt; rule in the Nginx config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/ws/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;"upgrade"&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;
  
  
  Translating Complexity into Clarity
&lt;/h2&gt;

&lt;p&gt;Parallel to the technical work, I spent time crafting a &lt;strong&gt;one‑pager&lt;/strong&gt; that explains the platform to non‑technical stakeholders. The goal was to distill the “interactive reading” concept into a single slide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Static books lack immersion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: A web‑based environment that reacts to narrative cues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Higher engagement, new monetization via premium scenes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I used a simple diagram built in Figma, then exported it as an SVG and embedded it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"assets/interactive-reading.svg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Interactive Reading Flow"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Kathaverse: Minimalist Short Stories
&lt;/h2&gt;

&lt;p&gt;In the &lt;strong&gt;Kathaverse&lt;/strong&gt; project, I experimented with ultra‑short stories composed of a handful of scenes. Each scene is a JSON snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scene"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A lone lantern flickers in the dark alley."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dark_alley.mp3"&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;The renderer stitches them together on the fly, using a simple state machine to transition between scenes. The key insight: &lt;em&gt;you don’t need a complex engine to evoke emotion—just the right order of small, well‑crafted moments.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Comic Strip Smoothness
&lt;/h2&gt;

&lt;p&gt;I revisited an old comic strip project to tighten frame transitions. Using &lt;strong&gt;GSAP&lt;/strong&gt; I added a subtle easing function that guides the eye:&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;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.frame&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="na"&gt;opacity&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="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;power2.out&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;stagger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a fluid flow that feels “right” without being obvious. Small tweaks like this accumulate into a polished experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  Personal Recharge
&lt;/h2&gt;

&lt;p&gt;Between code and design, I let myself unwind with &lt;em&gt;Scorpion&lt;/em&gt; episodes and a playlist of Bad Bunny &amp;amp; Jhay Cortez. The music helped clear mental clutter, making the next debugging session feel fresh.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day in Review
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frankenstein&lt;/strong&gt;: Scene orchestration, air‑visualization, particle throttling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shelf Platform&lt;/strong&gt;: API, WebSocket, Docker, DO deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication&lt;/strong&gt;: One‑pager, Figma diagram.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kathaverse&lt;/strong&gt;: Minimalist story engine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comic&lt;/strong&gt;: GSAP frame easing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self‑care&lt;/strong&gt;: Media breaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each task, though distinct, fed into a common goal: making narrative feel alive. The day felt cohesive because every small improvement added a layer of realism.&lt;/p&gt;




&lt;p&gt;Stay tuned for the next post where I’ll dive into the analytics layer—tracking how users interact with the scenes and how that data can inform future story design.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Soul in Motion — 6:20 PM | 2026-09-14</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Mon, 14 Sep 2026 13:51:32 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-620-pm-2026-09-14-256m</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-620-pm-2026-09-14-256m</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Refactored &lt;strong&gt;Soulvoice&lt;/strong&gt; TTS pipeline for a more natural voice.&lt;/li&gt;
&lt;li&gt;Fixed a device‑specific bug in the phone assistant, enabling true conversational behavior.&lt;/li&gt;
&lt;li&gt;Expanded &lt;strong&gt;Living‑Books&lt;/strong&gt; to add reverence modes for sacred texts.&lt;/li&gt;
&lt;li&gt;Automated YouTube pipeline dashboard to auto‑name streams by activity.&lt;/li&gt;
&lt;li&gt;Completed legal documentation; now free to focus on tech.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Morning – Soulvoice
&lt;/h2&gt;

&lt;p&gt;I spent the first part of the day deep in the &lt;strong&gt;Soulvoice&lt;/strong&gt; text‑to‑speech stack. The goal was to strip away layers of legacy code that had accumulated over months of incremental fixes. The refactor focused on how raw audio data is ingested and pre‑processed before hitting the neural TTS model.&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="c1"&gt;# before
&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_raw_audio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;trim_silence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;features&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_features&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tts_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# after
&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;preprocess_audio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tts_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;preprocess_audio&lt;/code&gt; helper now handles normalization, silence trimming, and feature extraction in a single pass, reducing latency by ~30 ms. The result? Voices that sound less like a “strained machine” and more like the original speaker. The biggest win was the cleaner API surface for downstream services.&lt;/p&gt;




&lt;h2&gt;
  
  
  Friday – Assistant on the Phone
&lt;/h2&gt;

&lt;p&gt;A device‑specific issue had been nagging the phone assistant for weeks. The assistant was only recognizing a handful of commands because the device’s speech recognizer was returning a truncated key. When a teammate handed me a new access key, the assistant’s “brain” suddenly had the full context it needed.&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;# Update the key in the device’s config&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ASSISTANT_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"new-key-12345"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the key swap, the assistant behaved like a real conversational partner instead of a simple command taker. I added a quick sanity check in the &lt;code&gt;assistant.py&lt;/code&gt; module to log key validity on startup:&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;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;validate_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ASSISTANT_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid assistant key&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;This small guard will catch similar regressions in the future.&lt;/p&gt;




&lt;h2&gt;
  
  
  Afternoon – Living‑Books
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Living‑Books&lt;/strong&gt; platform needed a richer emotional palette, especially for sacred texts. I added &lt;em&gt;reverence modes&lt;/em&gt; for the Gita, Quran, and Bible. The core idea is to flag a text as “sacred” and adjust the tone, pacing, and emphasis accordingly.&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="c1"&gt;# book.yaml&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Bhagavad&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Gita"&lt;/span&gt;
&lt;span class="na"&gt;genre&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sacred&lt;/span&gt;
&lt;span class="na"&gt;reverence_mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the rendering engine, a simple flag check now triggers a different set of prosody parameters:&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;if&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reverence_mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;prosody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_reverence_prosody&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;prosody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_standard_prosody&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The platform now treats sacred texts with the weight they deserve, distinguishing them from thrillers or other genres.&lt;/p&gt;




&lt;h2&gt;
  
  
  Legal Work
&lt;/h2&gt;

&lt;p&gt;Drafting a legal document for my lawyer was a necessary but mundane task. I used a template and filled in the specifics for the upcoming partnership. Once the lawyer reviewed it, the document was signed and filed—no more legal backlog for the next sprint.&lt;/p&gt;




&lt;h2&gt;
  
  
  YouTube Pipeline Dashboard
&lt;/h2&gt;

&lt;p&gt;I automated the YouTube pipeline dashboard so each data pipeline names itself based on its real‑time activity. The previous manual bookkeeping was error‑prone and time‑consuming.&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;# Example of auto‑naming logic&lt;/span&gt;
&lt;span class="nv"&gt;pipeline_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$activity&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'[:upper:]'&lt;/span&gt; &lt;span class="s1"&gt;'[:lower:]'&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script now runs as a cron job that updates the dashboard every minute. I also pulled in an older audio‑processing side project to keep everything running smoothly, ensuring that the new naming logic doesn’t interfere with existing metrics.&lt;/p&gt;




&lt;h2&gt;
  
  
  Evening
&lt;/h2&gt;

&lt;p&gt;After a day of precision and experimentation, I unwound with &lt;em&gt;Blade Runner 2049&lt;/em&gt; and a few episodes of &lt;em&gt;Rick and Morty&lt;/em&gt;. The mix of mood and chaos is the perfect counterbalance to the day’s technical grind.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking Back
&lt;/h2&gt;

&lt;p&gt;No single headline moment, but five solid wins:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A more human‑sounding voice in Soulvoice.&lt;/li&gt;
&lt;li&gt;An assistant that truly knows its device.&lt;/li&gt;
&lt;li&gt;A library that respects sacred texts.&lt;/li&gt;
&lt;li&gt;A self‑naming dashboard that cuts manual bookkeeping.&lt;/li&gt;
&lt;li&gt;Legal paperwork finally done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything moved forward, and tomorrow looks just as full. For now, this is enough.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>Soul in Motion — 6:15 PM | 2026-09-11</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Fri, 11 Sep 2026 13:20:18 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-615-pm-2026-09-11-5do8</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-615-pm-2026-09-11-5do8</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Morning frustration with a flaky voice‑assistant forced a deeper dive into the code, not just a quick patch.&lt;/li&gt;
&lt;li&gt;Re‑architected the assistant’s command‑handling loop, added robust error handling, and deployed a new build.&lt;/li&gt;
&lt;li&gt;Late‑night testing on a real device revealed UI/UX regressions that were fixed before the next day.&lt;/li&gt;
&lt;li&gt;Parallel work on &lt;strong&gt;Living‑Books&lt;/strong&gt; tackled scroll, audio, and font‑loading bugs with incremental fixes.&lt;/li&gt;
&lt;li&gt;Balancing work with deliberate breaks (TV, sports, anime) helped maintain focus and prevent burnout.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Morning: When “It Works Yesterday” Breaks Today
&lt;/h2&gt;

&lt;p&gt;It’s Friday, and the assistant on my phone—call it &lt;em&gt;Friday&lt;/em&gt;—is half‑alive. It hears my voice, but the responses are empty, the digital equivalent of a nod with no content. I’m staring at my laptop, coffee still untouched, and the irritation is real: &lt;em&gt;Why does this keep happening? Why do I have to fix you every single day?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Instead of patching the symptom, I decided to ask &lt;em&gt;why&lt;/em&gt; it was failing. I pulled up the repository that powers Friday’s intent‑recognition and response generation and went line by line. The code that decides what Friday hears and how she responds is a mix of a lightweight intent parser and a small state machine that decides how many turns to allow before timing out. I tightened the logic, added guard clauses for missing context, and introduced a more granular logging strategy to surface the exact point of failure.&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="c1"&gt;# Simplified example of the intent handler
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_intent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intent&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;if&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt; &lt;span class="ow"&gt;is&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;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No intent detected&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I didn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t catch that.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;intent_resolver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intent&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;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;log&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error resolving intent &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&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="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sorry, something went wrong.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After committing the changes, I built a new Docker image, pushed it to the registry, and rolled it out to the staging environment. The new build was ready for a quick test on the phone.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Device Test: Real‑World Reality Check
&lt;/h2&gt;

&lt;p&gt;I opened the same link on the phone in front of a friend. Books I could tap on worked, but music, ambient sound, and other small details vanished, as if the app forgot half of what it knew the second it left my laptop screen. This is the humility of building for real people on real devices: it works perfectly where you built it and falls apart everywhere else.&lt;/p&gt;

&lt;p&gt;The culprit turned out to be a race condition in the audio‑loading pipeline. The app would start fetching the audio stream before the UI had finished rendering the container, causing a &lt;code&gt;NullPointerException&lt;/code&gt; on Android and a silent failure on iOS. I fixed it by deferring the audio request until the &lt;code&gt;onLayout&lt;/code&gt; callback fired.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Android example&lt;/span&gt;
&lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;onLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bottom&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="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;audioPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audioUrl&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;After the patch, the phone no longer froze, and the assistant responded as expected.&lt;/p&gt;




&lt;h2&gt;
  
  
  Afternoon: Living‑Books – Making Stories Feel Like Places
&lt;/h2&gt;

&lt;p&gt;The second half of the day was spent on &lt;strong&gt;Living‑Books&lt;/strong&gt;, a project that turns static stories into interactive, place‑based experiences. The bugs were smaller but just as stubborn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scroll on Phone&lt;/strong&gt; – The bookshelf component used a &lt;code&gt;ScrollView&lt;/code&gt; that didn’t respect the &lt;code&gt;overflow&lt;/code&gt; property on mobile. I replaced it with a &lt;code&gt;FlatList&lt;/code&gt; that lazily renders items and added momentum scrolling.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FlatList&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;keyExtractor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&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="nx"&gt;horizontal&lt;/span&gt;
  &lt;span class="nx"&gt;showsHorizontalScrollIndicator&lt;/span&gt;&lt;span class="o"&gt;=&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="nx"&gt;onScroll&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Animated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;nativeEvent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;contentOffset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;scrollX&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;useNativeDriver&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;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audio Never Turns On&lt;/strong&gt; – The audio player was initialized with a stale &lt;code&gt;src&lt;/code&gt; attribute. I switched to a dynamic import that re‑initializes the player whenever the &lt;code&gt;audioUrl&lt;/code&gt; changes.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audioUrl&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;player&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;AudioPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audioUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setPlayerInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;audioUrl&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fonts Loading Slowly&lt;/strong&gt; – The web font loader was configured to load all fonts at once, causing a blocking render. I moved the font loading to a separate worker and used &lt;code&gt;font-display: swap&lt;/code&gt; in CSS to avoid invisible text.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@font-face&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'Open Sans'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url('/fonts/OpenSans.woff2')&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;'woff2'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;font-display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;swap&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;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After fixing each issue, I watched the page paint instantly, the shelf glide smoothly, and the atmosphere stay light enough for a phone. The satisfaction of seeing the UI finally behave as intended is oddly therapeutic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Breaks That Keep the Brain Fresh
&lt;/h2&gt;

&lt;p&gt;I took deliberate breaks to reset my focus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scorpion&lt;/strong&gt; – The show’s accurate plot‑twist predictions were a meditative distraction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Station Agent&lt;/strong&gt; – A quiet evening that let me decompress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Football&lt;/strong&gt; – Quick check on Messi’s retirement status and Real Madrid news.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anime Recommendations&lt;/strong&gt; – Browsed but never acted on, keeping the mind engaged without committing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rick and Morty&lt;/strong&gt; – A light‑hearted finale to the day.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These breaks helped me return to the code with fresh eyes and prevented the “I’ll watch this for fifteen minutes” trap from turning into an hour.&lt;/p&gt;




&lt;h2&gt;
  
  
  Evening Reflection: From Frustration to Relief
&lt;/h2&gt;

&lt;p&gt;By the time I looked up, it was late. I sat for a moment and tallied it up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The voice assistant that used to ignore me now mostly responds.&lt;/li&gt;
&lt;li&gt;The book platform that froze on the device most people will actually use now mostly runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither sounds impressive on paper, but I remember the morning frustration and the evening relief. The distance between those feelings is the whole point of doing this work.&lt;/p&gt;

&lt;p&gt;I’m not pretending to be superhuman. I get tired, I get short with things that don’t work, I lose an hour to a TV show I meant to watch for fifteen minutes. Yet something that was broken this morning isn’t broken tonight, in two completely different corners of my life, because I refused to leave it that way. Maybe that’s the trick: not being superhuman, just stubborn enough, day after day, that it starts to look like something else from afar.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Did You Get Done Today?
&lt;/h2&gt;

&lt;p&gt;Share your wins, your frustrations, and the small victories that keep you moving forward. Building is a marathon, not a sprint, and every bug fixed is a step closer to a product that actually works for people.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>devops</category>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Soul in Motion — 6:16 PM | 2026-09-10</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Thu, 10 Sep 2026 13:09:38 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-616-pm-2026-09-10-3k2c</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-616-pm-2026-09-10-3k2c</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built an interactive &lt;em&gt;Frankenstein&lt;/em&gt; demo that animates scenes based on the text, including subtle air‑visualization.&lt;/li&gt;
&lt;li&gt;Expanded the concept into a shelf‑level platform, deploying a 10‑chapter book with scene sequencing and mood‑based weather.&lt;/li&gt;
&lt;li&gt;Tackled plumbing: data ingestion, scene orchestration, and secure hosting on a cloud platform.&lt;/li&gt;
&lt;li&gt;Parallel work: concise product explanations, Kathaverse short‑story scaffolding, comic frame transitions, and personal media breaks.&lt;/li&gt;
&lt;li&gt;All projects progressed incrementally; each small fix added realism and cohesion.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  From Page to Space: Making &lt;em&gt;Frankenstein&lt;/em&gt; Breathable
&lt;/h2&gt;

&lt;p&gt;The core idea was simple: turn a static text into a living environment.&lt;br&gt;&lt;br&gt;
I started with a &lt;strong&gt;react‑three-fiber&lt;/strong&gt; scene that loads the book’s JSON representation, then maps each chapter to a &lt;code&gt;Scene&lt;/code&gt; component. The component adjusts lighting, background audio, and particle effects based on metadata extracted from the text (e.g., “dark, stormy night”).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Scene&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;chapter&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;mood&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;weather&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseMetadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chapter&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ambientLight&lt;/span&gt; &lt;span class="na"&gt;intensity&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mood&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;audio&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;weatherAudio&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;weather&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AirParticles&lt;/span&gt; &lt;span class="na"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;chapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;air&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;group&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Invisible Air Effect
&lt;/h3&gt;

&lt;p&gt;The “air becomes visible” trick was a debugging win. I added a low‑opacity &lt;strong&gt;cloud&lt;/strong&gt; particle system that only activates when the text mentions “air” or “wind.” It’s almost imperceptible, but it grounds the reader in the environment.&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;function&lt;/span&gt; &lt;span class="nf"&gt;AirParticles&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="p"&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;points&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;bufferGeometry&lt;/span&gt; &lt;span class="nx"&gt;attach&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;geometry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;cloudGeometry&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;pointsMaterial&lt;/span&gt; &lt;span class="nx"&gt;attach&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;material&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;opacity&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;transparent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/points&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The challenge was keeping the particles from over‑rendering. I throttled updates to once per second and used GPU instancing to keep the frame rate above 60 fps.&lt;/p&gt;




&lt;h2&gt;
  
  
  Scaling Up: From One Book to a Shelf
&lt;/h2&gt;

&lt;p&gt;After polishing the single‑book demo, I built a &lt;strong&gt;shelf&lt;/strong&gt; abstraction. Each book is a &lt;code&gt;ShelfItem&lt;/code&gt; that holds its own scene graph, metadata, and a small REST API for fetching the next chapter.&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="c1"&gt;# shelf.yaml&lt;/span&gt;
&lt;span class="na"&gt;books&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frankenstein&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Frankenstein"&lt;/span&gt;
    &lt;span class="na"&gt;chapters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/books/frankenstein/chapters/1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;great_expectations&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Great&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Expectations"&lt;/span&gt;
    &lt;span class="na"&gt;chapters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;
    &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/books/great_expectations/chapters/1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API is a lightweight Node/Express server that serves chapter JSON and a WebSocket for real‑time updates (e.g., when a user marks a bookmark).&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&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;app&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;WebSocket&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;ws&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="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;server&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="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;/books/:id/chapters/:num&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="nx"&gt;res&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="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`./data/&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;params&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="s2"&gt;/chapter&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;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&lt;/span&gt;&lt;span class="p"&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="nx"&gt;ws&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;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;message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&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;// broadcast bookmark updates&lt;/span&gt;
    &lt;span class="nx"&gt;wss&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;forEach&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="nx"&gt;client&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;msg&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;h3&gt;
  
  
  Deployment Pipeline
&lt;/h3&gt;

&lt;p&gt;I containerized the stack with Docker and pushed it to a &lt;strong&gt;DigitalOcean App Platform&lt;/strong&gt; instance. The pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;docker build -t mybooks:latest .&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker push registry.digitalocean.com/myorg/mybooks:latest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Deploy via the DO dashboard, exposing port 80.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The only real plumbing hurdle was ensuring the WebSocket endpoint survived the platform’s HTTP load balancer. I added a &lt;code&gt;proxy_pass&lt;/code&gt; rule in the Nginx config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/ws/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;"upgrade"&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;
  
  
  Translating Complexity into Clarity
&lt;/h2&gt;

&lt;p&gt;Parallel to the technical work, I spent time crafting a &lt;strong&gt;one‑pager&lt;/strong&gt; that explains the platform to non‑technical stakeholders. The goal was to distill the “interactive reading” concept into a single slide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Static books lack immersion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: A web‑based environment that reacts to narrative cues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: Higher engagement, new monetization via premium scenes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I used a simple diagram built in Figma, then exported it as an SVG and embedded it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"assets/interactive-reading.svg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Interactive Reading Flow"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Kathaverse: Minimalist Short Stories
&lt;/h2&gt;

&lt;p&gt;In the &lt;strong&gt;Kathaverse&lt;/strong&gt; project, I experimented with ultra‑short stories composed of a handful of scenes. Each scene is a JSON snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scene"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A lone lantern flickers in the dark alley."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dark_alley.mp3"&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;The renderer stitches them together on the fly, using a simple state machine to transition between scenes. The key insight: &lt;em&gt;you don’t need a complex engine to evoke emotion—just the right order of small, well‑crafted moments.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Comic Strip Smoothness
&lt;/h2&gt;

&lt;p&gt;I revisited an old comic strip project to tighten frame transitions. Using &lt;strong&gt;GSAP&lt;/strong&gt; I added a subtle easing function that guides the eye:&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;gsap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.frame&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="na"&gt;opacity&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="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;power2.out&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;stagger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a fluid flow that feels “right” without being obvious. Small tweaks like this accumulate into a polished experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  Personal Recharge
&lt;/h2&gt;

&lt;p&gt;Between code and design, I let myself unwind with &lt;em&gt;Scorpion&lt;/em&gt; episodes and a playlist of Bad Bunny &amp;amp; Jhay Cortez. The music helped clear mental clutter, making the next debugging session feel fresh.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day in Review
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frankenstein&lt;/strong&gt;: Scene orchestration, air‑visualization, particle throttling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shelf Platform&lt;/strong&gt;: API, WebSocket, Docker, DO deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication&lt;/strong&gt;: One‑pager, Figma diagram.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kathaverse&lt;/strong&gt;: Minimalist story engine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comic&lt;/strong&gt;: GSAP frame easing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self‑care&lt;/strong&gt;: Media breaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each task, though distinct, fed into a common goal: making narrative feel alive. The day felt cohesive because every small improvement added a layer of realism.&lt;/p&gt;




&lt;p&gt;Stay tuned for the next post where I’ll dive into the analytics layer—tracking how users interact with the scenes and how that data can inform future story design.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Soul in Motion — 5:56 PM | 2026-09-07</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Mon, 07 Sep 2026 12:48:39 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-556-pm-2026-09-07-19di</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-556-pm-2026-09-07-19di</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bluetooth on the laptop disappeared without warning; troubleshooting stalled.&lt;/li&gt;
&lt;li&gt;Cleaned up Docker containers and unused apps to reclaim disk space.&lt;/li&gt;
&lt;li&gt;Worked on five projects: &lt;em&gt;Manifest&lt;/em&gt;, &lt;em&gt;Unreal&lt;/em&gt;, &lt;em&gt;Living Books&lt;/em&gt;, &lt;em&gt;The Station Agent&lt;/em&gt;, and a music‑video rabbit hole.&lt;/li&gt;
&lt;li&gt;Minor progress on each: small edits, core interaction fixes, and iterative design tweaks.&lt;/li&gt;
&lt;li&gt;Evening was spent winding down with TV, music, and cricket highlights.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Daily Grind – 5:56 PM
&lt;/h2&gt;

&lt;p&gt;I started the day with a quiet frustration: my laptop’s Bluetooth had just vanished. No error messages, no warnings, just gone. I tried a handful of quick fixes—re‑enabling the adapter in &lt;code&gt;Settings&lt;/code&gt;, restarting the &lt;code&gt;bluetoothd&lt;/code&gt; service, and even rebooting the machine—but nothing worked. I set it aside for the moment, because the real work had to take priority. Some problems have to wait.&lt;/p&gt;




&lt;h2&gt;
  
  
  Morning: Digital House‑Keeping
&lt;/h2&gt;

&lt;p&gt;The first thing I did was a bit of digital housekeeping. I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker system prune &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then removed a handful of old applications that had quietly eaten up a lot of space. Seeing the drive breathe again gives a small, unreasonable satisfaction. It’s a reminder that even in a busy day, keeping the environment lean can save a lot of friction later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project 1: Manifest – Studio‑Like Decision Making
&lt;/h2&gt;

&lt;p&gt;After the cleanup, I shifted into &lt;em&gt;Manifest&lt;/em&gt;. This project is all about deliberate, small‑scale decisions that feel more like running a tiny studio than engineering. I spent the morning weighing what stays, what goes, and what’s worth building versus what sounded good yesterday. The process is less about code and more about a clear, intentional roadmap.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project 2: Unreal – Core Interaction Fixes
&lt;/h2&gt;

&lt;p&gt;Next, I dove into the Unreal side. I was working through core interactions until objects and characters finally responded to each other. The satisfying click of two systems finally talking is a good reminder that sometimes the hardest part is getting the plumbing to work. I tweaked a few Blueprint nodes and adjusted physics settings to get the desired response.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project 3: Living Books – A Rabbit Hole
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Living Books&lt;/em&gt; turned into a rabbit hole again. Every time I think I’ve settled on an interactive presentation, I find another way to improve it and start over. I closed the coding stretch with a short, focused pass on Friday: small edits that don’t look like much individually but make the app feel more thoughtful. The iterative nature of this project keeps me on my toes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project 4: The Station Agent – Quiet Hour
&lt;/h2&gt;

&lt;p&gt;Evening slowed down with a quiet hour of &lt;em&gt;The Station Agent&lt;/em&gt;. I let the show’s calm pace ground me after a day of rapid switching. It’s a nice contrast to the frantic pace of coding.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project 5: Music‑Video Rabbit Hole
&lt;/h2&gt;

&lt;p&gt;I also spent a bit of time on a music‑video rabbit hole that left Jon Bellion’s “I Will Find You” stuck in my head. The looping of the track and the visuals made for a surprisingly productive break.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrap‑Up
&lt;/h2&gt;

&lt;p&gt;By the time I looked up, Bluetooth was still broken, five projects had each moved forward a little, and I’d unintentionally found a new favorite song. Tomorrow I’ll pick the fight with Bluetooth again. For tonight, that’s enough.&lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>automation</category>
      <category>productivity</category>
      <category>docker</category>
    </item>
    <item>
      <title>Soul in Motion — 9:35 PM | 2026-09-02</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Wed, 02 Sep 2026 16:26:31 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-935-pm-2026-09-02-2jh3</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-935-pm-2026-09-02-2jh3</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Wake‑word detection is the hardest part of a voice assistant; reliability hinges on low‑latency, low‑power listening.&lt;/li&gt;
&lt;li&gt;Inconsistent request latency usually signals hidden state corruption or resource contention—debugging requires state snapshots and profiling.&lt;/li&gt;
&lt;li&gt;Incremental “small‑fix” work on core logic (e.g., edge‑case handling, retry loops) compounds into a noticeably smoother system over weeks.&lt;/li&gt;
&lt;li&gt;Balancing heavy‑lifting (wake‑word) with lighter tasks (content editing, environment setup) keeps the day productive and prevents burnout.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Building Friday‑Phone
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Listening Problem
&lt;/h3&gt;

&lt;p&gt;The first thing I tackled was the &lt;strong&gt;Friday‑Phone&lt;/strong&gt; wake‑word detector. In a voice assistant, the listening thread is the gatekeeper: if it never hears its own name, nothing downstream runs. The code lives in a tight, low‑latency loop that pulls audio frames from the microphone, feeds them through a lightweight neural network, and emits a trigger event when the confidence score crosses a threshold.&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;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;THRESHOLD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;trigger_event&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem I hit was &lt;em&gt;inconsistent latency&lt;/em&gt;. One request would fire in a few milliseconds, the next would stall for an indeterminate amount of time. There was no obvious exception, just a silent slowdown. In practice, this is how real systems behave: they don’t throw clean errors; they just become slower or produce odd outputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnosing the Slowdown
&lt;/h3&gt;

&lt;p&gt;The first step was to capture a timeline of the thread’s state. I added a simple profiler that logs timestamps for each stage:&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;time&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;t0&lt;/span&gt; &lt;span class="o"&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;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&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;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;t2&lt;/span&gt; &lt;span class="o"&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;monotonic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;THRESHOLD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;trigger_event&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;t3&lt;/span&gt; &lt;span class="o"&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;monotonic&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s predict:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;t2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s total:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;t3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t0&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;s&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;The logs revealed that the &lt;code&gt;predict&lt;/code&gt; call was the culprit on the slow runs. The model was a small TensorFlow Lite graph, but the CPU was being throttled by other background processes (e.g., a nightly backup script). Switching to a dedicated CPU core and pinning the process resolved the issue.&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;# Pin the process to core 3&lt;/span&gt;
taskset &lt;span class="nt"&gt;-c&lt;/span&gt; 3 ./friday-phone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that tweak, the latency stabilized around 15 ms per request, which is acceptable for a wake‑word detector.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project C – Incremental Core Logic
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The “Forty Small Things” Mindset
&lt;/h3&gt;

&lt;p&gt;Later in the day I moved to &lt;strong&gt;Project C&lt;/strong&gt;, the assistant’s core logic. This isn’t about solving a single hard problem; it’s about tightening dozens of edge cases that slip through in production. The changes I made were tiny: adding a retry guard for a flaky API, normalizing user input before passing it to the LLM, and tightening the timeout on a database query.&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;def&lt;/span&gt; &lt;span class="nf"&gt;safe_api_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="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;3&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;external_api&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="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;TimeoutError&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="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;API unreachable&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;Each tweak is a &lt;em&gt;micro‑optimization&lt;/em&gt; that, when compounded, reduces the overall error rate. Over weeks, the assistant feels more responsive and less prone to “I don’t understand” responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging the Assistant
&lt;/h3&gt;

&lt;p&gt;A recurring issue was the assistant occasionally returning a stale response. I introduced a simple cache invalidation strategy:&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="n"&gt;cache&lt;/span&gt; &lt;span class="o"&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;get_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;expired&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;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CacheEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&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;resp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if the same query is repeated within a minute, the assistant serves the cached answer, cutting down on latency and avoiding repeated LLM calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  Side Projects &amp;amp; Mental Reset
&lt;/h2&gt;

&lt;p&gt;After the heavy lifting, I switched gears to &lt;strong&gt;Kathaverse&lt;/strong&gt;: thumbnail generation, reading, and light editing. These tasks are low‑cognitive‑load but keep the workflow moving. I also set up a minimal environment for a new project, but let it sit while I focused on the urgent tasks.&lt;/p&gt;

&lt;p&gt;The afternoon also included a brief detour to a &lt;strong&gt;Hoyoverse&lt;/strong&gt; trailer at Gamescom. A two‑minute clip that reset my focus and reminded me that I’m still a kid who loves games. These little breaks are essential for maintaining a creative spark.&lt;/p&gt;




&lt;h2&gt;
  
  
  End‑of‑Day Routine
&lt;/h2&gt;

&lt;p&gt;The day closed with a familiar rhythm: a long YouTube session of gaming clips and tech tutorials, a quick Instagram scroll, and an evening of VLC playback. Watching &lt;em&gt;Rick and Morty&lt;/em&gt; and &lt;em&gt;A Few Good Men&lt;/em&gt; provided a mental palate cleanser and, oddly enough, new lines that I hadn’t noticed before.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reflections &amp;amp; Next Steps
&lt;/h2&gt;

&lt;p&gt;Today wasn’t about a breakthrough; it was about persistence through friction. The wake‑word detector finally behaved, the core logic got a few more edge‑case fixes, and the side projects nudged forward. Some days feel like sprinting; today felt more like sanding—one pass at a time, trusting the surface will smooth out eventually.&lt;/p&gt;

&lt;p&gt;Tomorrow I’ll dive back into the wake‑word system, hoping the latency improvements hold under load. If all goes well, the Friday‑Phone will finally be the silent, reliable gatekeeper it was meant to be.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>Soul in Motion — 9:22 PM | 2026-09-01</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Tue, 01 Sep 2026 16:15:59 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-922-pm-2026-09-01-4jbm</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-922-pm-2026-09-01-4jbm</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Confirmed mail‑integration for voice recognition on Project C was running after repeated checks.&lt;/li&gt;
&lt;li&gt;Decided to build a personal assistant on the phone, focusing on NLU, voice recognition, and API stitching.&lt;/li&gt;
&lt;li&gt;Tightened wake‑word detection to avoid false positives in noisy environments.&lt;/li&gt;
&lt;li&gt;Documented decisions in Chronicle to avoid future reverse‑engineering.&lt;/li&gt;
&lt;li&gt;Ended the day with a successful end‑to‑end wake‑word test, reinforcing confidence in the system.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Daily Loop: From Doubt to Delivery
&lt;/h2&gt;

&lt;p&gt;The day started with a nagging question: &lt;em&gt;Is the mail‑integration for voice recognition on Project C actually working?&lt;/em&gt;&lt;br&gt;&lt;br&gt;
I pinged the endpoint, watched the logs, and ran a quick integration test. Three different approaches—manual curl, automated test suite, and a live demo—all confirmed the service was up and stable. Yet the gap between &lt;em&gt;“it should work”&lt;/em&gt; and &lt;em&gt;“I’ve actually seen it work”&lt;/em&gt; lingered. That feeling of uncertainty is a developer’s silent partner; it pushes you to double‑check until the system behaves predictably.&lt;/p&gt;


&lt;h2&gt;
  
  
  Building a Personal Assistant
&lt;/h2&gt;

&lt;p&gt;The real pivot came when I said out loud, &lt;em&gt;“I want my own assistant, not a generic Google bot.”&lt;/em&gt;&lt;br&gt;&lt;br&gt;
The answer was simple: &lt;strong&gt;you can build it&lt;/strong&gt;. The stack is a mix of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Natural‑Language Understanding&lt;/strong&gt; – a lightweight intent classifier trained on my own voice data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voice Recognition&lt;/strong&gt; – a custom wake‑word model tuned to my accent and environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Stitching&lt;/strong&gt; – a micro‑service layer that routes intents to the appropriate external services (email, calendar, weather, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I sketched the architecture in a quick diagram (not shown here) and started wiring the components. The key takeaway: &lt;em&gt;the “now” idea is only a few commits away from a working prototype.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Chronicle: Documenting Decisions
&lt;/h2&gt;

&lt;p&gt;Between coding sessions I opened Chronicle to log the rationale behind each design choice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; Wake‑word threshold set to 0.85 to reduce false positives.
&lt;span class="p"&gt;-&lt;/span&gt; Email API uses OAuth2 with a short‑lived refresh token.
&lt;span class="p"&gt;-&lt;/span&gt; Intent classifier trained on 200 labeled utterances.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These notes feel unglamorous, but they save future‑me from re‑implementing logic that was already decided. In the long run, a well‑maintained Chronicle is a developer’s safety net.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tightening Wake‑Word Detection
&lt;/h2&gt;

&lt;p&gt;Wake‑word detection is the &lt;em&gt;anchor&lt;/em&gt; of any voice assistant. It has to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Listen&lt;/strong&gt; for a single phrase in a noisy background.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trigger&lt;/strong&gt; the assistant without lag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid&lt;/strong&gt; false positives that waste battery and annoy the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I iterated on the model by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collecting ambient noise samples from my office.&lt;/li&gt;
&lt;li&gt;Fine‑tuning the acoustic model with those samples.&lt;/li&gt;
&lt;li&gt;Running a 24‑hour test loop to catch edge cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result? The wake‑word now responds cleanly to &lt;em&gt;“Hey Friday”&lt;/em&gt; even with a coffee machine humming in the background.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reflecting on Responsible AI
&lt;/h2&gt;

&lt;p&gt;A quick detour: I read Eightfold.ai’s take on responsible AI in hiring. The principles—fairness, transparency, accountability—apply equally to a personal assistant. Building something that &lt;em&gt;people can trust&lt;/em&gt; means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data privacy&lt;/strong&gt;: store voice data locally whenever possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explainability&lt;/strong&gt;: log intent decisions so I can audit them later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bias mitigation&lt;/strong&gt;: test the assistant across different accents and dialects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These considerations shaped how I designed the intent classifier and how I handle user data.&lt;/p&gt;




&lt;h2&gt;
  
  
  End‑to‑End Wake‑Word Test
&lt;/h2&gt;

&lt;p&gt;The day closed with a full test:&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;# Start the wake‑word service&lt;/span&gt;
./start_wake_word.sh

&lt;span class="c"&gt;# Simulate a user saying the phrase&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hey Friday"&lt;/span&gt; | ./simulate_speech.sh

&lt;span class="c"&gt;# Verify the assistant triggers&lt;/span&gt;
curl http://localhost:8080/assistant/trigger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output was clean: the assistant activated, logged the trigger, and queued the next action. No crashes, no false alarms. A quiet confirmation that the pieces I built earlier are holding together.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Building Friday Looks Like
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hundreds of tiny “yes, that works now” moments&lt;/strong&gt; stack into a reliable system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Patient, iterative work&lt;/strong&gt; beats overnight miracles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt; turns fleeting insights into reusable knowledge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tomorrow, I’ll keep refining the wake‑word model, add more intents, and continue documenting every step. The goal is simple: a personal assistant that feels like having someone in my corner.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Soul in Motion — 1:43 PM | 2026-08-31</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Mon, 31 Aug 2026 08:34:56 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-143-pm-2026-08-31-mh5</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-143-pm-2026-08-31-mh5</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Identified a privacy issue from user feedback and dug into the root cause.&lt;/li&gt;
&lt;li&gt;Implemented tighter data handling and clearer UI cues to improve trust.&lt;/li&gt;
&lt;li&gt;Balanced rapid fixes with deeper analysis of pacing in a popular show.&lt;/li&gt;
&lt;li&gt;Kept the day productive with routine bookkeeping and incremental improvements.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Day in a Nutshell
&lt;/h2&gt;

&lt;p&gt;I started the morning after someone flagged a privacy concern that had surfaced in a recent session. It wasn’t a catastrophic bug—just a subtle lapse that could erode user trust. The real challenge was turning that complaint into a systemic improvement.&lt;/p&gt;

&lt;h3&gt;
  
  
  From Feedback to Insight
&lt;/h3&gt;

&lt;p&gt;I pulled the user’s comment and a handful of similar notes from our issue tracker. The goal was to separate the surface complaint from the underlying pattern. In practice that meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mapping the data flow&lt;/strong&gt;: Where was the personal information captured, stored, and transmitted?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identifying the weakest link&lt;/strong&gt;: Was it an accidental data leak, an ambiguous consent prompt, or a missing encryption step?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern that emerged was a lack of explicit consent and weak encryption on a few endpoints that handled user profiles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concrete Fixes
&lt;/h3&gt;

&lt;p&gt;By midday I had a concrete plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data Minimization&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strip unnecessary fields from the &lt;code&gt;User&lt;/code&gt; model before persisting.
&lt;/li&gt;
&lt;li&gt;Use a &lt;code&gt;SELECT&lt;/code&gt; projection to fetch only what the UI needs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encryption at Rest&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;   &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
   &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;encrypted_email&lt;/span&gt; &lt;span class="nb"&gt;VARBINARY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;encrypted_email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AES_ENCRYPT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;encryption_key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;COLUMN&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clear Privacy Cues&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Updated the consent modal to use plain language and a single “Agree” button.
&lt;/li&gt;
&lt;li&gt;Added a tooltip on the profile edit page explaining why each field is required.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These changes were low‑impact but high‑value: no new features, just a tighter grip on personal data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lunch &amp;amp; Reflection
&lt;/h3&gt;

&lt;p&gt;I ate lunch while watching the Test match between Australia and Bangladesh. A multi‑day cricket game feels oddly grounding when you’re knee‑deep in code. It reminded me that some problems—like pacing in a show—are just as much about rhythm as they are about content.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Afternoon Dive
&lt;/h3&gt;

&lt;p&gt;Later, I got sidetracked by a question that had been nagging me: why does the first season of a highly‑rated show feel sluggish? I spent a few hours watching episodes, noting pacing, episode length, and narrative structure. It turned out to be a pacing issue rather than a lack of quality. I documented my observations and shared them with the content team for future reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Routine Bookkeeping
&lt;/h3&gt;

&lt;p&gt;I also tackled some bookkeeping: updating the sprint backlog, reconciling the budget spreadsheet, and reviewing the CI pipeline logs for any anomalies. These unglamorous tasks keep the project from derailing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evening Wrap‑Up
&lt;/h3&gt;

&lt;p&gt;By the end of the day, the privacy fix was merged, the UI cues were live, and the pacing notes were in the shared doc. No drama, just incremental progress toward a product that earns trust.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Takeaways
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Privacy by Design
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Minimization&lt;/strong&gt;: Only collect what you need.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encryption&lt;/strong&gt;: Use AES‑256 for sensitive fields.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consent&lt;/strong&gt;: Explicit, granular, and revocable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Rapid Feedback Loops
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pull user feedback directly into your issue tracker.
&lt;/li&gt;
&lt;li&gt;Prioritize fixes that affect trust or security over cosmetic changes.
&lt;/li&gt;
&lt;li&gt;Deploy small, reversible changes to gauge impact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Balancing Speed and Depth
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Quick fixes are essential, but don’t ignore deeper patterns.
&lt;/li&gt;
&lt;li&gt;Use the time between fixes to dig into root causes—whether it’s data handling or content pacing.
&lt;/li&gt;
&lt;li&gt;Document findings for future reference; knowledge is a hidden feature.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Today’s work was a reminder that the most valuable engineering effort often comes from listening to users and tightening the seams that hold their trust together. The next day will bring more feedback, more analysis, and more incremental steps toward a product that feels safe and reliable.&lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>security</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Soul in Motion — 2:05 PM | 2026-08-29</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Sat, 29 Aug 2026 08:58:50 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-205-pm-2026-08-29-14oc</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-205-pm-2026-08-29-14oc</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Spent the day juggling six different codebases, each moving a few percent forward.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project C&lt;/strong&gt;: Design sprint turned into a new game feel; morning collaboration, afternoon sanity‑check.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chronicle&lt;/strong&gt;: Focused on physics consistency in a 2D world—no new features, just trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Friday‑Phone&lt;/strong&gt;: Debugged voice‑pipeline bug, screenshot‑by‑screenshot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manifest&lt;/strong&gt;: Artistic alignment of crisis events and launch‑site sequence; visual direction finally clicked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manifest‑Unreal&lt;/strong&gt;: Cross‑checked simulation core against browser build for parity.&lt;/li&gt;
&lt;li&gt;Wrapped up with minor work on &lt;strong&gt;Transformed&lt;/strong&gt; and &lt;strong&gt;Tmp&lt;/strong&gt;; laid groundwork for future features.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Day in the Life of a Multi‑Project Builder
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Project C – The Never‑Ending Ladder
&lt;/h3&gt;

&lt;p&gt;The morning started with a design call for &lt;strong&gt;Project C&lt;/strong&gt;. A friend sent over a rough idea for the game’s feel, and the conversation quickly turned into an &lt;em&gt;argument‑as‑collaboration&lt;/em&gt;. We debated pacing, control responsiveness, and the visual style until we landed on a concept that felt tighter than the last iteration. By lunch the scope had shifted just enough to keep the momentum going without derailing the sprint.&lt;/p&gt;

&lt;p&gt;After the design freeze, I spent the afternoon running sanity checks on the new assets and ensuring the ladder mechanics still behaved as expected. It’s the kind of work that feels invisible until something breaks, but it’s the foundation that keeps the rest of the project stable.&lt;/p&gt;




&lt;h3&gt;
  
  
  Chronicle – Precision Over Speed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Chronicle&lt;/strong&gt; is a 2D simulation that relies on accurate physics to feel believable. I dedicated a long stretch of the day to tightening the world’s behavior: collision detection, gravity scaling, and object interactions. No new features were added; the goal was to make the existing mechanics &lt;em&gt;trustworthy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This kind of work is often overlooked, but a world that “holds together” is the difference between a fun experience and a chaotic mess. I ran a suite of regression tests and manually stepped through edge cases to confirm consistency.&lt;/p&gt;




&lt;h3&gt;
  
  
  Friday‑Phone – Debugging the Voice Pipeline
&lt;/h3&gt;

&lt;p&gt;In the afternoon, &lt;strong&gt;Friday‑Phone&lt;/strong&gt; demanded a different kind of patience. I chased a bug through the assistant’s voice pipeline, capturing screenshots at each stage to isolate the failure point. The process was incremental: tweak a parameter, re‑run, capture, compare. Each small step was a win, and eventually the voice output behaved as intended.&lt;/p&gt;




&lt;h3&gt;
  
  
  Manifest – Artistic Alignment
&lt;/h3&gt;

&lt;p&gt;The day’s next stop was &lt;strong&gt;Manifest&lt;/strong&gt;, where I focused on crisis events and the launch‑site sequence. The goal was to align the art direction with the narrative flow. I iterated on asset placement, timing, and visual cues until the system finally looked like the vision I’d imagined weeks ago. Seeing the art direction click into place was a relief that reminded me why the creative side matters as much as the code.&lt;/p&gt;




&lt;h3&gt;
  
  
  Manifest‑Unreal – Cross‑Platform Consistency
&lt;/h3&gt;

&lt;p&gt;Evening brought &lt;strong&gt;Manifest‑Unreal&lt;/strong&gt;, a cross‑checking exercise between the simulation core and its browser counterpart. I ran both builds side‑by‑side, comparing physics outputs, frame rates, and asset loading times. The meticulous work paid off: both builds now agree on key metrics, ensuring a consistent experience across platforms.&lt;/p&gt;




&lt;h3&gt;
  
  
  Transformed &amp;amp; Tmp – Laying Bricks for the Future
&lt;/h3&gt;

&lt;p&gt;I wrapped up the day with quick passes on &lt;strong&gt;Transformed&lt;/strong&gt; and &lt;strong&gt;Tmp&lt;/strong&gt;. These were not breakthrough moments but essential housekeeping: refactoring a few functions, tightening type annotations, and adding a couple of unit tests. Small, incremental work that keeps the codebase healthy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Side Notes &amp;amp; Reflections
&lt;/h2&gt;

&lt;p&gt;Between the code, I let my mind wander a bit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Netflix&lt;/strong&gt;: A quick break with &lt;em&gt;Rocket Singh&lt;/em&gt;—a grounded, funny sci‑fi that was a nice left turn from my usual diet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ChatGPT &amp;amp; VS Code&lt;/strong&gt;: Tinkered with a fresh Visual Studio install and experimented with ChatGPT prompts to see how it could aid my workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eli’s Live Build&lt;/strong&gt;: Checked in on Eli’s live build to see how she’s holding up in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking back, the day wasn’t defined by a single big win. It was defined by momentum: six projects nudged forward, none finished, all a bit more real than they were in the morning. That’s the essence of building—just moving forward, one commit at a time.&lt;/p&gt;

&lt;p&gt;Onward to tomorrow.&lt;/p&gt;

</description>
      <category>indiehackers</category>
      <category>productivity</category>
      <category>learning</category>
      <category>career</category>
    </item>
    <item>
      <title>Soul in Motion — 3:06 PM | 2026-08-27</title>
      <dc:creator>Dev Rajput</dc:creator>
      <pubDate>Thu, 27 Aug 2026 10:00:58 +0000</pubDate>
      <link>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-306-pm-2026-08-27-38mf</link>
      <guid>https://dev.to/dev_rajput_2d46f92f8a3418/soul-in-motion-306-pm-2026-08-27-38mf</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Re‑engineered Horizon’s auth flow to be both secure and user‑friendly, adding graceful error handling for mistyped passwords, dropped connections, and double submissions.&lt;/li&gt;
&lt;li&gt;Experimented with a Rails‑based LLM that auto‑generates code from plain‑English descriptions; early results show promise but still need refinement.&lt;/li&gt;
&lt;li&gt;Audited Eli’s UX to eliminate friction points, enabling seamless re‑entry after breaks and reducing silent churn.&lt;/li&gt;
&lt;li&gt;Added six customizable “rooms” (light/dark, warm/quiet) to Eli, giving users contextual environments that influence comfort and engagement.&lt;/li&gt;
&lt;li&gt;The core mantra, &lt;em&gt;“Free AI can answer you. Eli is built to hold you.”&lt;/em&gt;, drives every design and implementation decision.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Re‑thinking Authentication in Horizon
&lt;/h2&gt;

&lt;p&gt;The first half of the day was all about the login flow. I had been iterating on Horizon’s authentication for weeks, each pass tightening security while shaving latency. The last iteration finally felt right: a single‑page login that validates credentials via a GraphQL mutation, then issues a short‑lived JWT and a refresh token stored in an HTTP‑only cookie.&lt;/p&gt;

&lt;h3&gt;
  
  
  Graceful Failure
&lt;/h3&gt;

&lt;p&gt;What really mattered was the &lt;em&gt;experience&lt;/em&gt; when something went wrong. Instead of a generic “invalid credentials” page, I wrapped the mutation in a &lt;code&gt;try/catch&lt;/code&gt; block that catches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AuthenticationError&lt;/code&gt; – wrong password&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NetworkError&lt;/code&gt; – dropped connection&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ValidationError&lt;/code&gt; – double submission&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each error maps to a specific, user‑friendly message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_login_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;AuthenticationError&lt;/span&gt;
    &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:alert&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"That username or password doesn't match our records."&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;NetworkError&lt;/span&gt;
    &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:alert&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Connection lost. Please check your internet and try again."&lt;/span&gt;
  &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;ValidationError&lt;/span&gt;
    &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:alert&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"We detected a duplicate request. Please wait a moment."&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;flash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:alert&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Something went wrong. Try again later."&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The messages are intentionally vague enough to avoid giving attackers hints, yet specific enough to guide legitimate users. I also added a debounce on the submit button to prevent double submissions at the UI level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Invisible but Critical
&lt;/h3&gt;

&lt;p&gt;These changes are buried three layers deep: the GraphQL resolver, the Rails controller, and the front‑end component. No one sees them unless something breaks, but when they do, the system fails &lt;em&gt;kindly&lt;/em&gt;. That’s the kind of invisible kindness I like to build.&lt;/p&gt;




&lt;h2&gt;
  
  
  Rails + LLM: Turning Sentences into Code
&lt;/h2&gt;

&lt;p&gt;After Horizon settled, I dove into a side project: a Rails app that uses an LLM to generate Ruby code from plain‑English prompts. The goal is to prototype a “code‑as‑service” layer that could one day power Eli’s dynamic room generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prompt Engine&lt;/strong&gt; – a thin wrapper around OpenAI’s &lt;code&gt;gpt-4o-mini&lt;/code&gt; API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Validator&lt;/strong&gt; – runs the generated code through &lt;code&gt;rubocop&lt;/code&gt; and a unit‑test harness to catch syntax errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feedback Loop&lt;/strong&gt; – user corrections are fed back into the prompt to improve future generations.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Gemfile&lt;/span&gt;
gem &lt;span class="s1"&gt;'openai'&lt;/span&gt;, &lt;span class="s1"&gt;'~&amp;gt; 3.0'&lt;/span&gt;
gem &lt;span class="s1"&gt;'rubocop'&lt;/span&gt;, &lt;span class="s1"&gt;'~&amp;gt; 1.50'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CodeGenerator&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;OpenAI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="s2"&gt;"gpt-4o-mini"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;messages: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;role: &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="s2"&gt;"You are a helpful Ruby developer."&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;role: &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="vi"&gt;@prompt&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="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"choices"&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="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&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="no"&gt;RuboCop&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Early Results
&lt;/h3&gt;

&lt;p&gt;The model sometimes produces a working snippet on the first try, especially for straightforward tasks like “create a Rails migration for a users table.” More complex logic, like a service object that interacts with an external API, still requires a few rounds of correction. Still, the fact that it can generate a &lt;em&gt;complete&lt;/em&gt; method from a single sentence is a glimpse of what a future AI‑assisted developer might look like.&lt;/p&gt;




&lt;h2&gt;
  
  
  Eli: From One Room to Six
&lt;/h2&gt;

&lt;p&gt;Eli is a conversational companion built on top of the same authentication stack. The second half of the day was dedicated to polishing the user journey.&lt;/p&gt;

&lt;h3&gt;
  
  
  UX Audit
&lt;/h3&gt;

&lt;p&gt;I walked through every point where a user might silently lose interest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Session Expiry&lt;/strong&gt; – implemented silent refresh using the refresh token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Navigation Gaps&lt;/strong&gt; – added “Continue where you left off” prompts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onboarding&lt;/strong&gt; – simplified the first‑time flow to a single screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These fixes reduce friction and keep users engaged.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Six Rooms
&lt;/h3&gt;

&lt;p&gt;The real fun came with the “rooms” feature. Each room is a pre‑configured set of UI themes and background audio that changes the user’s context:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Room&lt;/th&gt;
&lt;th&gt;Theme&lt;/th&gt;
&lt;th&gt;Audio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Light, warm&lt;/td&gt;
&lt;td&gt;Café chatter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Dark, quiet&lt;/td&gt;
&lt;td&gt;Library hush&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Light, cool&lt;/td&gt;
&lt;td&gt;Beach waves&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Dark, warm&lt;/td&gt;
&lt;td&gt;Fireplace crackle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Light, neutral&lt;/td&gt;
&lt;td&gt;City traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Dark, cool&lt;/td&gt;
&lt;td&gt;Night sky&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The implementation is a simple Rails view component that swaps CSS variables and plays an audio stream via the Web Audio API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RoomComponent&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ViewComponent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;room&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="vi"&gt;@room&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;room&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;theme_css&lt;/span&gt;
    &lt;span class="vi"&gt;@room&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;theme_css&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;audio_url&lt;/span&gt;
    &lt;span class="vi"&gt;@room&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;audio_url&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"room"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= theme_css %&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;audio&lt;/span&gt; &lt;span class="na"&gt;autoplay&lt;/span&gt; &lt;span class="na"&gt;loop&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= audio_url %&amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/audio&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;%=&lt;/span&gt; &lt;span class="na"&gt;render&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt; &lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users can switch rooms on the fly, and the app remembers their last choice in a &lt;code&gt;user_room&lt;/code&gt; column on the &lt;code&gt;users&lt;/code&gt; table.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Mantra
&lt;/h2&gt;

&lt;p&gt;A line I’d written weeks ago kept resurfacing: &lt;strong&gt;“Free AI can answer you. Eli is built to hold you.”&lt;/strong&gt; That sentence is the north star for every decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free AI&lt;/strong&gt; – the LLM that powers code generation and conversational responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hold you&lt;/strong&gt; – the gentle error handling, the frictionless re‑entry, the comforting rooms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything else—login flow, six rooms, quiet error messages—serves that promise.&lt;/p&gt;




&lt;h2&gt;
  
  
  Evening Reflections
&lt;/h2&gt;

&lt;p&gt;I wrapped up the day with a mix of media: &lt;em&gt;Rick and Morty&lt;/em&gt; for a dose of chaos, &lt;em&gt;Boardwalk Empire&lt;/em&gt; for sharp dialogue, a Joe Rogan clip for a lighter tone, and an unexpected &lt;em&gt;America’s Got Talent&lt;/em&gt; episode that actually kept me engaged. It’s a reminder that even when the code is solid, life still needs a little entertainment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Horizon&lt;/strong&gt; – still adding analytics to monitor authentication success rates and failure reasons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM Code Generator&lt;/strong&gt; – need to improve the feedback loop and add a sandbox for safe execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eli&lt;/strong&gt; – rooms are built, but I’ll start A/B testing to see which environments drive the most engagement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system that used to fail loudly now fails kindly, and a companion that had one room now has six. Tomorrow I’ll test whether these changes hold up under real traffic and user feedback.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
