<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Abdulkabir Musa</title>
    <description>The latest articles on Forem by Abdulkabir Musa (@aieradev).</description>
    <link>https://forem.com/aieradev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F668328%2Fde45ef88-1820-4a3b-95b1-c3d6b1d87f82.jpg</url>
      <title>Forem: Abdulkabir Musa</title>
      <link>https://forem.com/aieradev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/aieradev"/>
    <language>en</language>
    <item>
      <title>You Need Your Code to Be More Reliable Than People Using It</title>
      <dc:creator>Abdulkabir Musa</dc:creator>
      <pubDate>Wed, 10 Dec 2025 21:35:01 +0000</pubDate>
      <link>https://forem.com/aieradev/you-need-your-code-to-be-more-reliable-than-people-using-it-271o</link>
      <guid>https://forem.com/aieradev/you-need-your-code-to-be-more-reliable-than-people-using-it-271o</guid>
      <description>&lt;p&gt;There's a harsh truth about software development that many engineers learn the hard way: users will break your application in ways you never imagined possible. They'll enter dates in the wrong format, upload 50GB files to your profile picture field, click submit 47 times in rapid succession, and somehow manage to get your application into states you didn't even know existed.&lt;/p&gt;

&lt;p&gt;The knee-jerk reaction is often to blame the user. "They should have known better!" But here's the thing: &lt;strong&gt;your code needs to be more reliable than the people using it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reality of User Behavior
&lt;/h2&gt;

&lt;p&gt;Users don't read documentation. They don't carefully review error messages. They're distracted, in a hurry, or simply don't have the technical background to understand what your application expects. And that's perfectly fine—it's not their job to accommodate your code. It's your code's job to accommodate them.&lt;/p&gt;

&lt;p&gt;Consider these real-world scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A user copies text from a PDF that includes invisible Unicode characters&lt;/li&gt;
&lt;li&gt;Someone's internet connection drops mid-transaction&lt;/li&gt;
&lt;li&gt;A user navigates away from the page while your async operation is still running&lt;/li&gt;
&lt;li&gt;Someone clicks "back" after submitting a form&lt;/li&gt;
&lt;li&gt;A user leaves their session open for three days straight&lt;/li&gt;
&lt;li&gt;Multiple tabs of your application are open simultaneously&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these scenarios can break your application or corrupt data, that's not a user problem—that's a code reliability problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Reliability Actually Means
&lt;/h2&gt;

&lt;p&gt;Reliable code isn't just code that works under ideal conditions. It's code that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Validates rigorously&lt;/strong&gt; - Never trust input, even from your own frontend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fails gracefully&lt;/strong&gt; - When things go wrong, degrade functionality rather than crash&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handles edge cases&lt;/strong&gt; - The 99% case is important, but the 1% case is where bugs live&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintains data integrity&lt;/strong&gt; - No matter what users do, your data stays consistent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recovers automatically&lt;/strong&gt; - When possible, fix issues without user intervention&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Cost of Unreliable Code
&lt;/h2&gt;

&lt;p&gt;I once worked on a financial application where a race condition allowed users to double-submit wire transfers. The bug was rare—it required clicking submit twice within a 200ms window. "Users won't do that," we thought. But with thousands of users, "rare" happened daily. Each incident required manual intervention, customer service calls, and potential financial liability.&lt;/p&gt;

&lt;p&gt;The fix took two hours to implement: disable the button on first click and add idempotency keys. The cost of not implementing it from the start? Hundreds of hours of support time and damaged customer trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategies for Building Reliable Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Input Validation Everywhere
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad: Trust the frontend&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createUser&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Good: Validate everything&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createUser&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Throws on invalid data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sanitized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sanitizeInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validated&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sanitized&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;Never assume input is clean, even from your own UI. Browsers can be manipulated, APIs can be called directly, and middleware can fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Idempotency for All State Changes
&lt;/h3&gt;

&lt;p&gt;Every operation that changes state should be idempotent—running it multiple times should produce the same result as running it once.&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;# Bad: Can create duplicates
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;submit_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;items&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;order&lt;/span&gt;

&lt;span class="c1"&gt;# Good: Uses idempotency key
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;submit_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idempotency_key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_by_idempotency_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idempotency_key&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;existing&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;existing&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;idempotency_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;idempotency_key&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;order&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Defensive Database Operations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Bad: Assumes the record exists&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;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Good: Ensures constraints are maintained&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;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Then check affected rows to ensure it succeeded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Timeouts and Circuit Breakers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Bad: Wait forever for a response&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;externalAPI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Good: Fail fast with timeout&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&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;AbortController&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;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;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;5000&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;externalAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AbortError&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="c1"&gt;// Handle timeout gracefully&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fallbackResponse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Rate Limiting and Resource Protection
&lt;/h3&gt;

&lt;p&gt;Users will accidentally (or intentionally) hammer your endpoints. Your code needs to protect itself:&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;from&lt;/span&gt; &lt;span class="n"&gt;functools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;wraps&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rate_limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_calls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time_window&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;calls&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;decorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nd"&gt;@wraps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&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;wrapped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_current_user_id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;now&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;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="c1"&gt;# Clean old entries
&lt;/span&gt;            &lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;calls&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;user_id&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="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;time_window&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;max_calls&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rate limit exceeded&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;

            &lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user_id&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="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&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;wrapped&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;decorator&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Mindset Shift
&lt;/h2&gt;

&lt;p&gt;Building reliable code requires a mindset shift from "this should work" to "how could this fail?" Start asking questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens if this takes 10 seconds instead of 100ms?&lt;/li&gt;
&lt;li&gt;What if this function is called with null?&lt;/li&gt;
&lt;li&gt;What if two users do this at the exact same time?&lt;/li&gt;
&lt;li&gt;What if the network fails halfway through?&lt;/li&gt;
&lt;li&gt;What if this external service is down?&lt;/li&gt;
&lt;li&gt;What if someone sends me a 100MB string?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing for Reliability
&lt;/h2&gt;

&lt;p&gt;Unit tests are great, but they rarely catch reliability issues. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chaos testing&lt;/strong&gt; - Randomly kill processes, simulate network failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load testing&lt;/strong&gt; - See what breaks under pressure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fuzzing&lt;/strong&gt; - Send random garbage input and see what happens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrent testing&lt;/strong&gt; - Run multiple instances simultaneously&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-travel testing&lt;/strong&gt; - Test with system clocks set to edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Payoff
&lt;/h2&gt;

&lt;p&gt;Yes, building reliable code takes more time upfront. You'll write more validation logic, more error handling, more defensive checks. But the payoff is enormous:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fewer production incidents and 3 AM wake-up calls&lt;/li&gt;
&lt;li&gt;Reduced support burden&lt;/li&gt;
&lt;li&gt;Increased user trust&lt;/li&gt;
&lt;li&gt;Lower maintenance costs&lt;/li&gt;
&lt;li&gt;Better sleep at night&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Your users will make mistakes. They'll encounter network issues, browser quirks, and timing problems. They'll use your application in ways you never anticipated. That's not a bug in your users—it's the reality of building software for humans.&lt;/p&gt;

&lt;p&gt;The question isn't whether users will do unexpected things. The question is: when they do, will your code handle it gracefully, or will everything fall apart?&lt;/p&gt;

&lt;p&gt;Make your code more reliable than the people using it. Your future self (and your on-call rotation) will thank you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What reliability lessons have you learned the hard way? Share your war stories in the comments below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>I Built a Real-Time 1v1 Coding Battle Platform in Days Using Kiro</title>
      <dc:creator>Abdulkabir Musa</dc:creator>
      <pubDate>Thu, 04 Dec 2025 21:53:58 +0000</pubDate>
      <link>https://forem.com/aieradev/i-built-a-real-time-1v1-coding-battle-platform-in-days-using-kiro-25de</link>
      <guid>https://forem.com/aieradev/i-built-a-real-time-1v1-coding-battle-platform-in-days-using-kiro-25de</guid>
      <description>&lt;h2&gt;
  
  
  The Problem with LeetCode
&lt;/h2&gt;

&lt;p&gt;Let's be honest: grinding LeetCode is boring.&lt;/p&gt;

&lt;p&gt;You solve a problem. Green checkmark. Move on. Repeat. There's no excitement, no pressure, no reason to push beyond "it works."&lt;/p&gt;

&lt;p&gt;I wanted to change that. What if coding practice felt like a ranked match in your favorite game? What if you could watch your opponent's progress in real-time and race to submit first?&lt;/p&gt;

&lt;p&gt;That's how &lt;strong&gt;Phantom&lt;/strong&gt; was born—a real-time 1v1 competitive coding platform where developers battle head-to-head in algorithmic challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

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


  &lt;iframe src="https://www.youtube.com/embed/akK_MMC1KHA"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;Phantom features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live split-screen battles&lt;/strong&gt; - Watch your opponent code in real-time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered judging&lt;/strong&gt; - Google Gemini analyzes code quality and efficiency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strategic power-ups&lt;/strong&gt; - Time Freeze, Code Peek, Debug Shield&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ELO matchmaking&lt;/strong&gt; - Fair matches against similarly skilled opponents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cyberpunk UI&lt;/strong&gt; - Dark glassmorphism design with smooth animations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tech stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Next.js 14, React, TypeScript, TailwindCSS, Monaco Editor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Node.js, Express, Socket.io&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Databases:&lt;/strong&gt; PostgreSQL + Redis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Execution:&lt;/strong&gt; Judge0 Cloud API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Vercel + Railway&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Kiro Changed Everything
&lt;/h2&gt;

&lt;p&gt;I built Phantom for the Kiroween Hackathon, and Kiro's spec-driven development approach was transformational.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spec-Driven Development
&lt;/h3&gt;

&lt;p&gt;Instead of diving straight into code, every major feature started with structured specs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.kiro/specs/
├── phantom-code-battle/     # Core battle mechanics
├── power-ups-system/        # Strategic abilities
├── ai-code-coach/           # Gemini integration
├── judge0-cloud-integration/ # Code execution
└── authenticated-redirect/   # Auth flow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each spec contained:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;requirements.md&lt;/strong&gt; - What the feature must do&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;design.md&lt;/strong&gt; - Architecture, data models, API contracts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tasks.md&lt;/strong&gt; - Implementation checklist&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This structure forced me to think through edge cases &lt;em&gt;before&lt;/em&gt; writing code. For a real-time multiplayer system where race conditions lurk everywhere, this was invaluable.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pivot That Could Have Killed the Project
&lt;/h3&gt;

&lt;p&gt;Here's where Kiro really saved me.&lt;/p&gt;

&lt;p&gt;I built a beautiful Docker-based code execution system locally. Sandboxed containers, resource limits, network isolation—it worked perfectly.&lt;/p&gt;

&lt;p&gt;Then I tried deploying to Railway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Railway doesn't support Docker-in-Docker.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My entire code execution engine was unusable in production. With the hackathon deadline approaching, I had to completely rewrite the execution pipeline to use Judge0's cloud API instead.&lt;/p&gt;

&lt;p&gt;Because I had clear specs defining the interfaces and requirements, I could swap the execution layer without touching the battle logic. Kiro helped me plan the migration systematically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before: Docker execution&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;executeCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ExecutionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;docker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createContainer&lt;/span&gt;&lt;span class="p"&gt;({...});&lt;/span&gt;
  &lt;span class="c1"&gt;// ... container management&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// After: Judge0 API&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;executeCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ExecutionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;judge0Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;source_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;language_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LANGUAGE_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// ... same interface, different implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The spec-driven approach meant the rest of the codebase didn't care &lt;em&gt;how&lt;/em&gt; code was executed—just that it returned the expected result format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging Railway Deployment
&lt;/h3&gt;

&lt;p&gt;Deploying the backend to Railway was brutal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment variables needed specific formatting&lt;/li&gt;
&lt;li&gt;TypeScript errors only appeared in Railway's build environment&lt;/li&gt;
&lt;li&gt;Health checks kept timing out&lt;/li&gt;
&lt;li&gt;WebSocket connections dropped due to proxy issues&lt;/li&gt;
&lt;li&gt;The dashboard kept timing out during deploys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I hit walls, Kiro helped troubleshoot systematically. It analyzed error logs, suggested configuration fixes, and helped me understand Railway's specific requirements.&lt;/p&gt;

&lt;p&gt;Eventually, I deployed everything via Railway's CLI after the dashboard proved unreliable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;railway login
railway &lt;span class="nb"&gt;link
&lt;/span&gt;railway up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes the CLI just works better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real-Time Challenge
&lt;/h2&gt;

&lt;p&gt;Building multiplayer real-time features is genuinely hard. Here's what I learned:&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Socket.io event naming convention: action:resource&lt;/span&gt;
&lt;span class="nx"&gt;socket&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="s2"&gt;battle:join&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleJoin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;socket&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="s2"&gt;battle:submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;socket&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="s2"&gt;battle:sync&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSync&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;socket&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="s2"&gt;battle:powerup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handlePowerup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consistent naming made debugging much easier when events were flying between two players.&lt;/p&gt;

&lt;h3&gt;
  
  
  State Synchronization
&lt;/h3&gt;

&lt;p&gt;Keeping two editors in sync with sub-100ms latency required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis pub/sub for cross-instance communication&lt;/li&gt;
&lt;li&gt;Throttling to prevent event flooding&lt;/li&gt;
&lt;li&gt;State recovery for reconnections&lt;/li&gt;
&lt;li&gt;Optimistic updates on the client&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Race Conditions
&lt;/h3&gt;

&lt;p&gt;What happens when both players submit at the exact same moment? The spec forced me to define this upfront:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Correctness Properties&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; CP-1: Simultaneous submissions must be processed in arrival order
&lt;span class="p"&gt;-&lt;/span&gt; CP-2: A player cannot submit while their previous submission is being judged
&lt;span class="p"&gt;-&lt;/span&gt; CP-3: Battle state must remain consistent across disconnection/reconnection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Steering for Consistency
&lt;/h2&gt;

&lt;p&gt;Kiro's steering docs maintained consistency across the codebase:&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="gh"&gt;# coding-standards.md&lt;/span&gt;

&lt;span class="gu"&gt;## TypeScript Guidelines&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Use strict TypeScript configuration
&lt;span class="p"&gt;-&lt;/span&gt; Prefer interfaces over types for object shapes
&lt;span class="p"&gt;-&lt;/span&gt; Always define return types for functions

&lt;span class="gu"&gt;## Backend Conventions&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Controllers handle HTTP/WebSocket requests
&lt;span class="p"&gt;-&lt;/span&gt; Services contain business logic
&lt;span class="p"&gt;-&lt;/span&gt; Socket events follow &lt;span class="sb"&gt;`action:resource`&lt;/span&gt; naming
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without steering, Kiro would generate valid but inconsistent code. With steering, every file followed the same patterns—crucial for a full-stack TypeScript project.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Research deployment constraints first&lt;/strong&gt; - Check platform limitations before building. My Docker system was elegant but unusable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Start with the spec&lt;/strong&gt; - Even for hackathons, 30 minutes of requirements thinking saves hours of rewrites.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use the CLI&lt;/strong&gt; - When dashboards fail, CLIs are more reliable.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try Phantom
&lt;/h2&gt;

&lt;p&gt;🎮 &lt;strong&gt;Live Demo:&lt;/strong&gt; &lt;a href="https://kiroween-phantom.vercel.app" rel="noopener noreferrer"&gt;kiroween-phantom.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📂 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/AIEraDev/phantom" rel="noopener noreferrer"&gt;github.com/AIEraDev/phantom&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test accounts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;player1@test.com&lt;/code&gt; / &lt;code&gt;player1@test.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;player2@test.com&lt;/code&gt; / &lt;code&gt;player2@test.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open two browser windows, log in with both accounts, and start a battle to see the real-time sync in action.&lt;/p&gt;

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

&lt;p&gt;Kiro's spec-driven development isn't just about generating code—it's about thinking clearly before coding. The structured approach caught edge cases early, made the Judge0 migration possible under pressure, and kept a complex real-time system maintainable.&lt;/p&gt;

&lt;p&gt;Phantom started as a hackathon project, but the foundation is solid enough to build on. Next up: tournament brackets, more languages, and maybe ranked seasons.&lt;/p&gt;

&lt;p&gt;If you're building something complex with real-time features, give spec-driven development a try. Your future self debugging WebSocket race conditions at 2 AM will thank you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built for Kiroween Hackathon 2025 🎃&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  kiro
&lt;/h1&gt;

</description>
      <category>kiro</category>
      <category>hackathon</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
