<?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</title>
    <description>The most recent home feed on DEV Community.</description>
    <link>https://dev.to</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed"/>
    <language>en</language>
    <item>
      <title>Building in public, week 11: 143 pages indexed, a TinyPNG alternative in Rust</title>
      <dc:creator>Serhii Kalyna</dc:creator>
      <pubDate>Sun, 31 May 2026 11:15:26 +0000</pubDate>
      <link>https://dev.to/serhii_kalyna_730b636889c/building-in-public-week-11-143-pages-indexed-a-tinypng-alternative-in-rust-4n35</link>
      <guid>https://dev.to/serhii_kalyna_730b636889c/building-in-public-week-11-143-pages-indexed-a-tinypng-alternative-in-rust-4n35</guid>
      <description>&lt;p&gt;Week 11 of building &lt;a href="https://convertifyapp.net" rel="noopener noreferrer"&gt;Convertify&lt;/a&gt; a free image converter (Rust + Axum + libvips, Next.js SSG frontend) in public. Solo, no funding, 52-week run.&lt;/p&gt;

&lt;p&gt;Here's the honest headline: **indexing jumped from 100 to 143 pages, I shipped image compression in Rust, and my clicks are still stuck.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  1. Internal linking between blog and converter (the debt I kept dodging)
&lt;/h3&gt;

&lt;p&gt;I launched a blog in week 10 (3 posts, full schema, the works) and immediately got 18 views/week on one post. Great except that traffic had nowhere to go. The blog talked &lt;em&gt;about&lt;/em&gt; HEIC; it never pointed at the page that actually &lt;em&gt;converts&lt;/em&gt; HEIC.&lt;/p&gt;

&lt;p&gt;So week 11 I built a &lt;code&gt;RelatedArticle&lt;/code&gt; component and wired it both ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blog -&amp;gt; converter:&lt;/strong&gt; inline contextual links in the body + a CTA block at the end.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Converter -&amp;gt; blog:&lt;/strong&gt; a "Learn more" card driven by a &lt;code&gt;related_blog_slug&lt;/code&gt; column on each page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The component went through a small evolution. First version showed one article. Then I made it multi-article it pulls 2–3 related posts, matches them by topic via slug, caps at 3, and (the part that bit me) guards against the literal string &lt;code&gt;"NULL"&lt;/code&gt; sneaking in from a missing DB value. Nothing fancy, but it closes the loop: informational traffic can finally flow to the transactional pages.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Image compression a free TinyPNG alternative, in Rust.
&lt;/h3&gt;

&lt;p&gt;This was the fun one. TinyPNG does ~3M visits/month. That demand is enormous and I was leaving it on the table. libvips already gives me everything I need, so the backend was fast to stand up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JPEG -&amp;gt; mozjpeg.&lt;/strong&gt; libvips can hand JPEG encoding to mozjpeg, which does trellis quantization and smarter Huffman tables. Same visual quality, meaningfully smaller files than baseline libjpeg.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PNG -&amp;gt; imagequant.&lt;/strong&gt; This is the same lossy-PNG approach pngquant (and TinyPNG) use: quantize a 24-bit PNG down to an optimized palette. Huge size drops on PNGs with limited color, transparency preserved.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The UX is a quality slider (1-100%) and a before/after size readout, so you actually &lt;em&gt;see&lt;/em&gt; the reduction. I shipped three landing pages &lt;code&gt;/compress-jpg&lt;/code&gt;, &lt;code&gt;/compress-png&lt;/code&gt;, &lt;code&gt;/compress-webp&lt;/code&gt; positioned as the free alternative.&lt;/p&gt;

&lt;p&gt;The interesting signal: &lt;code&gt;Compress JPG Free&lt;/code&gt; pulled &lt;strong&gt;24 views in its first week&lt;/strong&gt;, landing straight in my top pages. Different user intent than conversion (people &lt;em&gt;converting&lt;/em&gt; a format vs people &lt;em&gt;shrinking&lt;/em&gt; a file), and it showed up immediately. That alone made the cluster worth it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Blog post #4
&lt;/h3&gt;

&lt;p&gt;"Why HEIC Files Won't Open" published, 8 FAQs, FAQ schema embedded in the &lt;code&gt;BlogPosting&lt;/code&gt;. Continuing the content momentum and feeding the new internal-linking machine.&lt;/p&gt;

&lt;p&gt;Also did a cannibalization audit across blog + landing pages. Came back clean: intent is cleanly split (blog = informational, landing = transactional), so they're not fighting each other in search.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Google Search Console (3 months):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Indexed: 100 -&amp;gt; &lt;strong&gt;143&lt;/strong&gt; (+43, second-biggest jump ever)&lt;/li&gt;
&lt;li&gt;Not indexed: 65 -&amp;gt; &lt;strong&gt;39&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Avg position: 40 -&amp;gt; &lt;strong&gt;39.5&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Google Analytics (7 days):&lt;/strong&gt; 31 active users (+29%), 24 new (+33%), 52 sessions (+11%).&lt;/p&gt;

&lt;p&gt;Traffic sources had a surprise: &lt;code&gt;l.threads.com&lt;/code&gt; sent 13 sessions in a week Threads quietly became a real referrer. &lt;code&gt;chatgpt.com&lt;/code&gt; has been a steady trickle for over a month now too (LLMs citing the blog posts).&lt;/p&gt;

&lt;h2&gt;
  
  
  Housekeeping wins
&lt;/h2&gt;

&lt;p&gt;Cleared a stack of small debts that were quietly rotting: fixed the 404 source (broken internal links), cleared the redirect errors flagged in GSC, and consolidated my project docs into a single source-of-truth file instead of three drifting documents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next week (12)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Two new tools that are low-effort / high-ROI: &lt;strong&gt;resize + crop&lt;/strong&gt; and &lt;strong&gt;background removal&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A compression-focused blog post to feed the new cluster.&lt;/li&gt;
&lt;li&gt;The real work: on-page pushes on my top-impression pages to &lt;em&gt;finally&lt;/em&gt; break something into the top 20.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've shipped a programmatic-SEO site and watched impressions climb while clicks flatlined I'd genuinely like to hear how (or whether) you broke out of it. That's the wall I'm at.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Convertify is built with Rust + libvips + Next.js. Following along week by week.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>rust</category>
      <category>seo</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Python Programming for Beginners – Day 4</title>
      <dc:creator>augustineowino357-design</dc:creator>
      <pubDate>Sun, 31 May 2026 11:14:36 +0000</pubDate>
      <link>https://dev.to/augustineowino357design/python-programming-for-beginners-day-4-249f</link>
      <guid>https://dev.to/augustineowino357design/python-programming-for-beginners-day-4-249f</guid>
      <description>&lt;p&gt;&lt;strong&gt;Python Operators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the previous lesson, we learned about Input and Output operations in Python. Today, we will learn about Operators, which are used to perform operations on variables and values.&lt;/p&gt;

&lt;p&gt;Operators are important in programming because they help perform calculations, comparisons, logical decisions, and data manipulation.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What are Operators?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Operators are special symbols used to perform operations on operands (values or variables).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"+" is the operator&lt;/li&gt;
&lt;li&gt;"x" and "y" are operands&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Types of Operators in Python&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python provides several types of operators:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Arithmetic Operators&lt;/li&gt;
&lt;li&gt;Assignment Operators&lt;/li&gt;
&lt;li&gt;Comparison Operators&lt;/li&gt;
&lt;li&gt;Logical Operators&lt;/li&gt;
&lt;li&gt;Identity Operators&lt;/li&gt;
&lt;li&gt;Membership Operators&lt;/li&gt;
&lt;li&gt;Bitwise Operators&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;1. Arithmetic Operators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Arithmetic Operators are used for mathematical calculations.&lt;br&gt;
&lt;strong&gt;Operator| Meaning| Example&lt;/strong&gt;&lt;br&gt;
"+"| Addition| "x + y"&lt;br&gt;
"-"| Subtraction| "x - y"&lt;br&gt;
"&lt;em&gt;"| Multiplication| "x * y"&lt;br&gt;
"/"| Division| "x / y"&lt;br&gt;
"%"| Modulus| "x % y"&lt;br&gt;
"&lt;/em&gt;&lt;em&gt;"| Exponent| "x *&lt;/em&gt; y"&lt;br&gt;
"//"| Floor Division| "x // y"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;23
17
60
6.666666666666667
2
8000
6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;2. Assignment Operators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Assignment Operators are used to assign values to variables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operator| Example&lt;/strong&gt;&lt;br&gt;
"="| "x = 5"&lt;br&gt;
"+="| "x += 3"&lt;br&gt;
"-="| "x -= 3"&lt;br&gt;
"*="| "x *= 3"&lt;br&gt;
"/="| "x /= 3"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;3. Comparison Operators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Comparison Operators compare two values and return either "True" or "False".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operator| Meaning&lt;/strong&gt;&lt;br&gt;
"=="| Equal to&lt;br&gt;
"!="| Not equal to&lt;br&gt;
"&amp;gt;"| Greater than&lt;br&gt;
"&amp;lt;"| Less than&lt;br&gt;
"&amp;gt;="| Greater than or equal to&lt;br&gt;
"&amp;lt;="| Less than or equal to&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;False
True
True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;4. Logical Operators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Logical Operators are used to combine conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operator| Meaning&lt;/strong&gt;&lt;br&gt;
"and"| Returns True if both conditions are True&lt;br&gt;
"or"| Returns True if at least one condition is True&lt;br&gt;
"not"| Reverses the result&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;True
True
False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;5. Identity Operators&lt;/strong&gt;&lt;br&gt;
Identity Operators compare memory locations of objects.&lt;/p&gt;

&lt;p&gt;Operator| Meaning&lt;br&gt;
"is"| Returns True if both variables are the same object&lt;br&gt;
"is not"| Returns True if variables are not the same object&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;6. Membership Operators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Membership Operators check whether a value exists in a sequence.&lt;/p&gt;

&lt;p&gt;Operator| Meaning&lt;br&gt;
"in"| Returns True if value exists&lt;br&gt;
"not in"| Returns True if value does not exist&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;python&lt;/span&gt;
&lt;span class="n"&gt;languages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&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;Java&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;C++&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PHP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plaintext
True
True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;7. Bitwise Operators&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bitwise Operators perform operations on binary numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operator| Meaning&lt;/strong&gt;&lt;br&gt;
"&amp;amp;"| AND&lt;br&gt;
&lt;code&gt;|&lt;/code&gt;&lt;br&gt;
"^"| XOR&lt;br&gt;
"~"| NOT&lt;br&gt;
"&amp;lt;&amp;lt;"| Left Shift&lt;br&gt;
"&amp;gt;&amp;gt;"| Right Shift&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Operator Precedence&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Python follows a specific order when evaluating expressions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;

&lt;span class="nf"&gt;print&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiplication happens before addition because it has higher precedence.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Why Operators are Important&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Operators help programmers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perform calculations&lt;/li&gt;
&lt;li&gt;Compare values&lt;/li&gt;
&lt;li&gt;Make decisions&lt;/li&gt;
&lt;li&gt;Build conditions&lt;/li&gt;
&lt;li&gt;Manipulate data&lt;/li&gt;
&lt;li&gt;Create dynamic programs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without operators, programming logic would not work effectively.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Operators are essential building blocks in Python programming. They allow programs to perform mathematical calculations, comparisons, logical decisions, and many other operations.&lt;/p&gt;

&lt;p&gt;Understanding operators is important because they are used in almost every Python program.&lt;/p&gt;

&lt;p&gt;Practice using different operators to become more comfortable with Python expressions and logic.&lt;/p&gt;

&lt;h1&gt;
  
  
  Python #PythonForBeginners #CodingJourney #LearnPython #Programming
&lt;/h1&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I built a World Cup prediction app with 0 frameworks, 100% privacy, and hit #1 on ChatGPT</title>
      <dc:creator>Aviatorpo</dc:creator>
      <pubDate>Sun, 31 May 2026 11:12:33 +0000</pubDate>
      <link>https://dev.to/aviatorpo/title-how-i-built-a-world-cup-prediction-app-with-0-frameworks-100-privacy-and-hit-1-on-chatgpt-38bp</link>
      <guid>https://dev.to/aviatorpo/title-how-i-built-a-world-cup-prediction-app-with-0-frameworks-100-privacy-and-hit-1-on-chatgpt-38bp</guid>
      <description>&lt;p&gt;Every time a major football tournament comes around, my friends and I set up a prediction pool. But every single year, the experience is the exact same frustration: legacy apps forcing everyone to fill out long signup forms, verify emails, dodge annoying ads, or deal with bloated interfaces that lag on a mobile browser.  &lt;/p&gt;

&lt;p&gt;I didn't want my friends to jump through hoops just to submit a few match guesses. I wanted something fast, clean, and frictionless.&lt;/p&gt;

&lt;p&gt;So, I sat down and built FriendlyBet ( &lt;a href="https://friendlybet.live" rel="noopener noreferrer"&gt;https://friendlybet.live&lt;/a&gt; ).  &lt;/p&gt;

&lt;p&gt;It’s a completely free, open-source (MIT), privacy-first World Cup 2026 prediction platform. And to make it a true engineering challenge, I built it with zero frontend frameworks.  &lt;/p&gt;

&lt;p&gt;Today, it has over 200 active pools running, and OpenAI’s ChatGPT is already recommending it as the #1 tool for World Cup prediction pools! Here is how it works under the hood and why skipping the modern framework hype was the best decision I made.&lt;br&gt;&lt;br&gt;
🚀 The Core Philosophy: Zero Friction, Total Privacy&lt;/p&gt;

&lt;p&gt;If you want sports fans (and casual users) to onboard into your app, every extra input field is an enemy. FriendlyBet has no signup forms, no email collection, and no phone verification.  &lt;/p&gt;

&lt;p&gt;Instead, users create or join a pool using a simple 5-character code. For authentication and recovery, the app generates a single 16-character plaintext key for the user, which is SHA-256 hashed and stored securely on the database. If they switch devices, they just paste their key. No passwords to forget, no data to leak.&lt;br&gt;&lt;br&gt;
🛠️ The Lean Tech Stack&lt;/p&gt;

&lt;p&gt;I deliberately chose a hyper-lean stack to ensure the app loads instantly, runs completely offline-first, and costs next to nothing to maintain:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend: Static HTML5 + Vanilla JavaScript + Pure CSS. No Webpack, no Vite, no Next.js, no compilation step.  

Database &amp;amp; Security: Supabase (PostgreSQL). By leveraging Row-Level Security (RLS), the client-side JavaScript communicates directly and safely with the database, removing the need for a dedicated middle-tier API server.  

The "Brain" (Automation): I don't run a persistent server for cron jobs. Instead, GitHub Actions scripts wake up on a scheduled cron, fetch live tournament data feeds, sync match statuses to Supabase, and trigger the leaderboard score calculations automatically.  

PWA Capability: Fully installable on iOS and Android with an offline-aware service worker caching the entire app infrastructure for instant boot times.  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;⚽ Smart Game Mechanics&lt;/p&gt;

&lt;p&gt;Because this was built by a football fan for football fans, I wanted the gameplay to be deep and strategic, not just standard score guessing:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Full Tournament Journey: Users rank all 12 groups, build out their entire knockout tree (from the Round of 32 down to the Final), and predict the Golden Boot top scorer.  

The Underdog Multiplier: To reward bold strategies, teams are dynamically grouped by FIFA rankings. Successfully predicting a massive upset by an Underdog nets the player a ×2 score multiplier, shaking up the group leaderboards.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;💡 What I Learned&lt;/p&gt;

&lt;p&gt;Building a modern, highly interactive single-page application (SPA) in Vanilla JS in 2026 reminded me of how powerful the web platform actually is out of the box.  &lt;/p&gt;

&lt;p&gt;Without the overhead of virtual DOMs and massive node_modules bundles, the app size is negligible, rendering performance is butter-smooth on ancient mobile phones, and deployment to Vercel takes literally seconds.  &lt;/p&gt;

&lt;p&gt;If you're planning your friend group's tournament pool or just want to check out a framework-free, privacy-first codebase, feel free to dive in!  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Live App: https://friendlybet.live



Source Code: GitHub Repository (MIT License)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I’d love to hear your thoughts on building serverless/frameworkless projects, or how you handle local state and routing in Vanilla JS! Let’s discuss in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>What I Learned Building a Redis Clone in C++</title>
      <dc:creator>Drishti Tripathi</dc:creator>
      <pubDate>Sun, 31 May 2026 11:05:41 +0000</pubDate>
      <link>https://dev.to/drishtitripathi2230/what-i-learned-building-a-redis-clone-in-c-450m</link>
      <guid>https://dev.to/drishtitripathi2230/what-i-learned-building-a-redis-clone-in-c-450m</guid>
      <description>&lt;h1&gt;
  
  
  What I Learned Building a Redis Clone in C++
&lt;/h1&gt;

&lt;p&gt;A few weeks ago I was studying backend development from first principles. Not frameworks, not tutorials that skip the hard parts — actual fundamentals. How does data get stored? How does a server talk to a client? What even is a database at its core?&lt;/p&gt;

&lt;p&gt;That's when I came across Redis for the first time.&lt;/p&gt;

&lt;p&gt;I was reading about caching and kept seeing Redis mentioned everywhere. I looked it up and found out it's just a key-value store — you give it a key, it gives you back a value. Fast. Simple. Used by Twitter, GitHub, Snapchat.&lt;/p&gt;

&lt;p&gt;And I thought: &lt;em&gt;how hard can it be to build something like that?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Spoiler: harder than I expected. But I learned more from this one project than from weeks of reading.&lt;/p&gt;

&lt;p&gt;Here's everything I built, everything I got wrong, and everything I learned.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Key-Value Store?
&lt;/h2&gt;

&lt;p&gt;Before I get into the code, let me explain what I was even building.&lt;/p&gt;

&lt;p&gt;A key-value store is the simplest possible database. Instead of tables and rows like SQL, it just stores pairs:&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="s2"&gt;"name"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"Drishti"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"age"&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"20"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"city"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s2"&gt;"Delhi"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You store something with a key. You retrieve it with the same key. That's it. Redis is the most popular key-value store in the world and it's used everywhere — caching, session storage, rate limiting, pub/sub messaging.&lt;/p&gt;

&lt;p&gt;My goal was to build a simplified version from scratch in C++ and compare it to the real thing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Plan
&lt;/h2&gt;

&lt;p&gt;I gave myself a clear roadmap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TCP server on port 6380&lt;/li&gt;
&lt;li&gt;GET / SET / DELETE commands&lt;/li&gt;
&lt;li&gt;LRU eviction (automatically remove old keys when store is full)&lt;/li&gt;
&lt;li&gt;Disk persistence (data survives server restarts)&lt;/li&gt;
&lt;li&gt;Benchmark against real Redis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me walk through each one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: The TCP Server
&lt;/h2&gt;

&lt;p&gt;The first thing I had to learn was how servers actually work at the socket level. I'd used HTTP APIs before but never thought about what happens underneath.&lt;/p&gt;

&lt;p&gt;A socket is just an endpoint for communication. When you connect to a server, both sides get a socket and they use it to send and receive data over TCP.&lt;/p&gt;

&lt;p&gt;Here's the core of my server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;SOCKET&lt;/span&gt; &lt;span class="n"&gt;server_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SOCK_STREAM&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="n"&gt;sockaddr_in&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin_family&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin_addr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;INADDR_ANY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sin_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;htons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6380&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sockaddr&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SOCKET&lt;/span&gt; &lt;span class="n"&gt;client_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// handle client...&lt;/span&gt;
    &lt;span class="n"&gt;closesocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_fd&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;In plain English:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a socket&lt;/li&gt;
&lt;li&gt;Bind it to port 6380&lt;/li&gt;
&lt;li&gt;Listen for connections&lt;/li&gt;
&lt;li&gt;In a loop — accept a client, handle them, close the connection&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why port 6380? Redis uses 6379. I wanted to run both simultaneously for benchmarking, so I picked the next port.&lt;/p&gt;

&lt;p&gt;One thing that caught me off guard: on Windows you have to explicitly initialize the socket library with &lt;code&gt;WSAStartup&lt;/code&gt; before using any socket functions. On Linux you don't need this. Small difference, but it tripped me up at first.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Parsing Commands
&lt;/h2&gt;

&lt;p&gt;Once the server could accept connections, I needed it to actually understand commands.&lt;/p&gt;

&lt;p&gt;The client sends a raw string like &lt;code&gt;"set name Drishti"&lt;/code&gt;. My server receives it as a buffer of bytes. I needed to split it into tokens:&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="s2"&gt;"set name Drishti"&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;→&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"set"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Drishti"&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;I wrote a parser that splits the string by spaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;parse_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;npos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&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;tokens&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;Then handle each command based on &lt;code&gt;tokens[0]&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"set"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tokens&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"get"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"delete"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;erase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One bug I hit early: telnet sends &lt;code&gt;\r\n&lt;/code&gt; at the end of each command. So &lt;code&gt;tokens[2]&lt;/code&gt; would be &lt;code&gt;"Drishti\r\n"&lt;/code&gt; instead of &lt;code&gt;"Drishti"&lt;/code&gt;. The fix was trimming trailing whitespace and newlines before parsing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: LRU Eviction
&lt;/h2&gt;

&lt;p&gt;This was the most interesting part to implement.&lt;/p&gt;

&lt;p&gt;The problem: memory is finite. If clients keep adding keys forever, the store will eventually run out of memory. I needed a way to automatically remove old keys when the store gets full.&lt;/p&gt;

&lt;p&gt;LRU — Least Recently Used — removes the key that hasn't been accessed in the longest time. The logic is simple: if you haven't used something recently, you probably don't need it.&lt;/p&gt;

&lt;p&gt;Example with capacity 5:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set a 1   →  [a]
set b 2   →  [a, b]
set c 3   →  [a, b, c]
set d 4   →  [a, b, c, d]
set e 5   →  [a, b, c, d, e]  ← full!
get a     →  [b, c, d, e, a]  ← 'a' just used, moves to front
set f 6   →  evict 'b' (least recently used)
             [c, d, e, a, f]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The implementation uses two data structures together:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A doubly linked list&lt;/strong&gt; tracks order of use. Most recently used is at the front, least recently used is at the back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A hash map&lt;/strong&gt; maps each key directly to its position in the list for O(1) lookup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List: [f] &amp;lt;-&amp;gt; [a] &amp;lt;-&amp;gt; [e] &amp;lt;-&amp;gt; [d] &amp;lt;-&amp;gt; [c]
Map:  "a" → node, "f" → node, ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neither structure alone is enough. The list gives you order but lookup is O(n). The map gives you fast lookup but has no concept of order. Together they give you both in O(1).&lt;/p&gt;

&lt;p&gt;Every GET or SET moves that key to the front of the list. When you need to evict, just remove from the back. That's it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Disk Persistence
&lt;/h2&gt;

&lt;p&gt;Without persistence, all data disappears when the server restarts. Not great.&lt;/p&gt;

&lt;p&gt;I implemented an Append-Only File (AOF) — the same strategy Redis uses. Every SET and DELETE gets logged to a file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set a 1
set b 2
set c 3
delete b
set d 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file only ever gets appended to — never edited or rewritten. On startup, the server reads the file top to bottom and replays every command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;replay: set a 1    →  {a=1}
replay: set b 2    →  {a=1, b=2}
replay: set c 3    →  {a=1, b=2, c=3}
replay: delete b   →  {a=1, c=3}
replay: set d 4    →  {a=1, c=3, d=4}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing this felt satisfying. Set some keys, kill the server, restart it, get the same keys back. It works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Benchmarks vs Redis
&lt;/h2&gt;

&lt;p&gt;The moment of truth. I installed Redis 7.0.15 on WSL and wrote a Python benchmark that sends 1000 SET and 1000 GET commands to both servers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;My KV Store&lt;/th&gt;
&lt;th&gt;Redis 7.0.15&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SET 1000 keys&lt;/td&gt;
&lt;td&gt;3.55s (281 req/s)&lt;/td&gt;
&lt;td&gt;3.19s (313 req/s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET 1000 keys&lt;/td&gt;
&lt;td&gt;3.55s (281 req/s)&lt;/td&gt;
&lt;td&gt;1.12s (892 req/s)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;SET is almost equal&lt;/strong&gt; — only 11% slower. Honestly didn't expect that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GET has a 3x gap&lt;/strong&gt; — Redis is significantly faster here.&lt;/p&gt;

&lt;p&gt;But here's the thing: this comparison isn't entirely fair. And understanding &lt;em&gt;why&lt;/em&gt; it isn't fair taught me more than the numbers themselves.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Numbers Don't Tell You
&lt;/h2&gt;

&lt;p&gt;My benchmark script opens a new TCP connection for every single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;connect → send "set a 1" → receive "OK" → disconnect
connect → send "get a"   → receive "1"  → disconnect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every TCP connection requires a 3-way handshake (SYN, SYN-ACK, ACK). That's network overhead on every single request. Real Redis clients use &lt;strong&gt;persistent connections&lt;/strong&gt; — one connection stays open and thousands of commands flow through it.&lt;/p&gt;

&lt;p&gt;My store isn't slow because C++ is slow. It's slow because of connection overhead that has nothing to do with the actual KV logic.&lt;/p&gt;

&lt;p&gt;This was one of the most valuable lessons from the project: &lt;strong&gt;benchmarks are only meaningful in context&lt;/strong&gt;. The numbers matter less than understanding what the numbers are actually measuring.&lt;/p&gt;




&lt;h2&gt;
  
  
  Other Limitations (Being Honest)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Single-threaded&lt;/strong&gt;: My server handles one request at a time. Redis uses event-driven I/O (epoll) to handle thousands of concurrent clients on a single thread. Production servers use async I/O or thread pools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AOF grows forever&lt;/strong&gt;: My file never gets compacted. Redis periodically rewrites the AOF to remove redundant entries — if a key was set 1000 times, only the last value matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No RESP protocol&lt;/strong&gt;: Real Redis uses RESP (Redis Serialization Protocol), a structured binary format. My store uses plain text, so it's not compatible with &lt;code&gt;redis-cli&lt;/code&gt; or any Redis SDK.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LRU capacity is hardcoded to 5&lt;/strong&gt;: Fine for a demo, not for production.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Actually Learned
&lt;/h2&gt;

&lt;p&gt;Going in, I thought this project would teach me about databases. It did — but it taught me much more than that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TCP sockets from scratch.&lt;/strong&gt; I now understand what actually happens when two programs communicate over a network. Before this, HTTP was magic to me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why data structures matter in practice.&lt;/strong&gt; LRU eviction is a textbook problem, but implementing it made the O(1) requirement real. You can't just use a list. You can't just use a map. You need both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gap between "working" and "production-grade".&lt;/strong&gt; My store works. Redis works at 1 million req/s under production load. Understanding that gap — connection pooling, async I/O, protocol design, crash recovery — is what separates a learning project from real infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benchmarking is a skill.&lt;/strong&gt; Writing a benchmark that actually measures what you think it's measuring is harder than it sounds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First principles learning works.&lt;/strong&gt; I could have used a Redis client library and moved on. Instead I built the thing. Now when I use Redis in a real project, I'll understand what it's doing.&lt;/p&gt;




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

&lt;p&gt;Full source code on GitHub: &lt;a href="https://github.com/DrishtiTripathi2230/kv-store" rel="noopener noreferrer"&gt;https://github.com/DrishtiTripathi2230/kv-store&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The README has a detailed breakdown of every component with diagrams and examples — worth a read if you want to understand any part in more depth.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tags: #cpp #systems #redis #showdev #beginners&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>showdev</category>
      <category>programming</category>
      <category>cpp</category>
    </item>
    <item>
      <title>When the Corporation Is the Regulator</title>
      <dc:creator>Tim Green</dc:creator>
      <pubDate>Sun, 31 May 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/rawveg/when-the-corporation-is-the-regulator-51np</link>
      <guid>https://dev.to/rawveg/when-the-corporation-is-the-regulator-51np</guid>
      <description>&lt;p&gt;When Brad Smith, Microsoft's vice chair and president, stood before cameras in December 2025 to announce his company's largest ever commitment to Canada, he did not simply unveil an infrastructure deal. He outlined a blueprint. The C$19 billion investment, spanning 2023 to 2027, with more than C$7.5 billion (approximately US$5.4 billion) earmarked for the next two years alone, was wrapped in the language of sovereignty, trust, and governance. Smith called it “the most robust digital sovereignty plan that we have announced anywhere,” building on commitments Microsoft had previously made to the European Union. But behind the soaring rhetoric lies a more complicated question, one that regulators, civil society groups, and rival governments are only beginning to wrestle with: can a single corporation's infrastructure investments actually create replicable models for responsible AI governance across jurisdictions with wildly divergent regulatory expectations?&lt;/p&gt;

&lt;p&gt;The answer matters. It matters because the sovereign cloud market is projected to grow from US$154.69 billion in 2025 to US$823.91 billion by 2032, according to Fortune Business Insights, with Europe expected to hold the highest market share. It matters because the EU AI Act is rolling out in phases that will reshape compliance requirements for every organisation deploying AI in Europe. And it matters because Canada itself has failed to pass comprehensive AI legislation, leaving a regulatory vacuum that corporate commitments are rushing to fill. Microsoft expects to spend US$80 billion on AI-enabled data centres in its fiscal year 2025 alone, according to a January 2025 blog post by Smith, with more than half of that spending directed at US facilities. The Canadian investment, while substantial, is one piece of a global infrastructure play that spans Portugal (US$10 billion), the United Arab Emirates (US$15 billion), and dozens of other markets.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Anatomy of a Sovereign AI Play
&lt;/h2&gt;

&lt;p&gt;To understand what Microsoft is attempting in Canada, you need to see the investment as more than data centres and fibre optic cables. The C$7.5 billion will expand Microsoft's Azure Canada Central (Toronto) and Canada East (Quebec City) data centre regions, with new capacity expected to come online in the second half of 2026. These facilities will be designed for energy efficiency, renewable power, and water-saving cooling systems, features that are increasingly non-negotiable given the enormous power demands of AI workloads. Nvidia's GB200 NVL72 systems, widely used in AI data centres, are estimated to consume up to 120 kilowatts per rack, demanding liquid cooling and advanced infrastructure management.&lt;/p&gt;

&lt;p&gt;Microsoft currently employs more than 5,300 people across 11 Canadian cities, operates a significant R&amp;amp;D hub in Vancouver with over 2,700 engineers, and supports an ecosystem of 17,000 partner companies that generate between C$33 billion and C$41 billion annually, supporting approximately 426,000 jobs. The company estimates that AI tools could generate up to C$40 billion in annual productivity gains for Canadian organisations. A 2025 Microsoft SMB Report found that 71% of Canadian small and medium businesses are actively using AI or generative AI, with 90% adoption among digital-native firms.&lt;/p&gt;

&lt;p&gt;But the infrastructure spend is only one layer of a five-point digital sovereignty plan that Smith articulated as a deliberate governance architecture. The five pillars cover cybersecurity defence, data residency, privacy protection, support for Canadian AI developers, and continuity of cloud services. Each pillar addresses a distinct governance concern, and together they represent Microsoft's attempt to demonstrate that a hyperscaler can operate within national boundaries while maintaining global interoperability. On the fifth pillar, Microsoft made a distinctive pledge: to pursue legal and diplomatic remedies against any order that would suspend cloud services to Canadian customers, a commitment that goes beyond standard service-level agreements.&lt;/p&gt;

&lt;p&gt;The cybersecurity pillar centres on a new Threat Intelligence Hub in Ottawa, staffed by Microsoft subject matter experts in threat intelligence, threat protection research, and applied AI security research. The hub will collaborate with the Royal Canadian Mounted Police (RCMP), the Canadian Centre for Cyber Security (part of the Communications Security Establishment), and other government agencies to monitor nation-state actors, ransomware groups, and AI-powered attacks. Microsoft claims access to 100 trillion daily threat signals globally, a figure that underscores the sheer scale of its intelligence apparatus. The company disclosed that its investigators had recently uncovered Chinese and North Korean operatives using fake identities for tech sector infiltration in Canada, lending urgency to the hub's establishment. Microsoft's own assessment found that in 2025, more than half of cyberattacks against Canada with known motives were financially motivated, with 80% involving data exfiltration efforts, and almost 20% targeting the healthcare and education sectors.&lt;/p&gt;

&lt;p&gt;On data residency, Microsoft committed to processing Copilot interactions within Canadian borders by 2026, expanding Azure Local to allow organisations to run Azure capabilities in their own private cloud and on-premises environments, and launching the Sovereign AI Landing Zone (SAIL), an open-source framework hosted on GitHub designed to provide a secure foundation for deploying AI solutions within Canadian borders while maintaining privacy and compliance standards. Canada is one of 15 countries to which Microsoft is extending in-country data processing for Microsoft 365 Copilot interactions; the initiative began rolling out to Australia, the United Kingdom, India, and Japan by the end of 2025, with 11 additional countries, including Canada, scheduled for 2026.&lt;/p&gt;

&lt;p&gt;The privacy pillar introduces confidential computing capabilities within Canadian data centre regions, keeping data encrypted and isolated even during processing. Azure Key Vault will be available to Canadian customers, supporting external key management and allowing encryption keys to remain under customer control. Microsoft has also made a contractual commitment to challenge any government demand for Canadian government or commercial customer data where it has a legal basis to do so.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Sovereignty Meets the Sovereign Landing Zone
&lt;/h2&gt;

&lt;p&gt;The technical architecture underpinning Microsoft's sovereignty claims is the Sovereign Landing Zone (SLZ), a variant of the Azure Landing Zone (ALZ) that layers additional controls for data residency, encryption, and operational oversight. In June 2025, Microsoft CEO Satya Nadella announced a broad range of sovereign cloud solutions, and the SLZ has since moved from concept to implementation. The SLZ on Terraform achieved general availability, with a Bicep implementation currently in development building on the new Bicep Azure Verified Modules for Platform Landing Zones.&lt;/p&gt;

&lt;p&gt;The SLZ is not a separate cloud. It builds on ALZ principles but applies tighter, enforceable controls aligned with sovereign operating models. The architecture includes management-group hierarchies tailored for workload classification (Public, Confidential Online, and Confidential Corp), additional policies for data residency, and encryption at rest, in transit, and in use through confidential computing. The key design principle is enforcement over guidance: guardrails are applied at the platform level using management groups, Azure Policy, identity controls, and standardised subscription layouts. Application teams can move quickly, but only within approved boundaries. In addition to Azure's built-in policies, the SLZ provides a Sovereignty Baseline Policy initiative alongside country-specific and regulation-specific policy sets, with the set of built-in policy definitions continuing to expand.&lt;/p&gt;

&lt;p&gt;For regulators, this architecture raises a fundamental question: does platform-level enforcement constitute genuine governance, or is it merely compliance theatre orchestrated by the very entity being regulated? The distinction matters enormously. When Microsoft embeds sovereignty controls into its infrastructure layer, it effectively sets the rules of the game. Customers can customise deployments in accordance with established regulatory frameworks. But the underlying infrastructure remains Microsoft's, subject to its design decisions, its threat models, and its commercial priorities.&lt;/p&gt;

&lt;p&gt;This tension is not hypothetical. Under the US CLOUD Act and the Foreign Intelligence Surveillance Act (FISA), data hosted on servers owned by US companies can be subject to US law enforcement requests, regardless of where those servers are physically located. The Canadian government itself characterised FISA as a “primary risk to data sovereignty” in a 2020 white paper. Microsoft's contractual commitment to challenge such demands is welcome, but it remains a voluntary corporate pledge, not a structural guarantee. Smith told CTV in December 2025 that “no country can defend its digital sovereignty if it cannot defend its digital borders,” adding that Microsoft defends Canada's digital border “every day.” That framing reveals a core paradox: digital sovereignty premised on the goodwill of a foreign corporation is sovereignty of a peculiar, contingent sort.&lt;/p&gt;

&lt;h2&gt;
  
  
  The EU AI Act and the Compliance Calendar
&lt;/h2&gt;

&lt;p&gt;Any discussion of replicable governance models must contend with the EU AI Act, the world's most comprehensive AI regulation, which is being implemented in phases that will reshape the compliance landscape through 2027 and beyond.&lt;/p&gt;

&lt;p&gt;The Act entered into force on 1 August 2024, but its requirements activate at different milestones. As of 2 February 2025, AI systems posing “unacceptable risks” became strictly prohibited, including manipulative AI, predictive policing, social scoring, and real-time biometric identification in public spaces. Organisations also became required to ensure adequate AI literacy among employees involved in AI deployment.&lt;/p&gt;

&lt;p&gt;On 2 August 2025, rules for general-purpose AI (GPAI) models took effect, requiring providers to maintain technical documentation, publish public summaries of training content using the European Commission's template, and comply with EU copyright rules. Member States were required to designate national competent authorities and adopt national laws on penalties. EU-level governance structures, including the AI Board, Scientific Panel, and Advisory Forum, had to be established.&lt;/p&gt;

&lt;p&gt;The majority of the Act's provisions become fully applicable on 2 August 2026, including requirements for high-risk AI systems in healthcare, finance, employment, and critical infrastructure. Transparency rules under Article 50 will apply, and each Member State should have established at least one AI regulatory sandbox. Full application, including rules for high-risk AI embedded in regulated products, arrives on 2 August 2027, with a final deadline of 31 December 2030 for AI systems that are components of large-scale IT systems.&lt;/p&gt;

&lt;p&gt;Finland has already moved ahead of the pack, activating national supervision laws on 1 January 2026 and becoming the first EU Member State with fully operational AI Act enforcement powers at the national level. On 2 February 2026, the European Commission conducted its first mandatory review of Article 5 prohibitions, potentially expanding the list of banned AI applications based on evidence of emerging risks. Meanwhile, in November 2025, the European Commission proposed the “Digital Omnibus,” a plan to simplify the EU's sweeping digital regulations, which could delay when certain high-risk obligations take effect; however, this proposal must still pass through the EU legislative process.&lt;/p&gt;

&lt;p&gt;For Microsoft, the EU AI Act creates both obligation and opportunity. The company has stated that its early investment in responsible AI positions it well to meet regulatory demands and to help customers do the same. Microsoft has already established a European board of directors, composed of European nationals, exclusively overseeing all data centre operations in compliance with European law. But the Act's requirements for explainability, auditability, and fairness documentation go far beyond what any single company's voluntary commitments have historically delivered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Canada's Regulatory Vacuum and the Corporate Governance Paradox
&lt;/h2&gt;

&lt;p&gt;While the EU is implementing the world's most detailed AI regulatory framework, Canada finds itself in a strikingly different position. The Artificial Intelligence and Data Act (AIDA), introduced as part of Bill C-27 in June 2022, was designed to establish a comprehensive regulatory framework for AI. It would have introduced measures to regulate AI systems, prohibited harmful practices, created a new AI and Data Commissioner, and imposed penalties of up to C$25 million or 5% of global revenue for non-compliance.&lt;/p&gt;

&lt;p&gt;AIDA never became law. The bill died on the order paper in January 2025 after extensive parliamentary scrutiny revealed concerns about its scope, the delegation of regulatory powers, and the adequacy of public consultations. Critics noted that key provisions were vague, including the lack of a clear definition for “high-impact system,” with the Act stating that the definition might evolve in the future. The Act was also criticised for having been developed behind closed doors by a select group of industry representatives, drawing criticism for its lack of broader stakeholder engagement.&lt;/p&gt;

&lt;p&gt;The current federal government has indicated it will seek to regulate AI through privacy legislation, policy, and investment rather than overarching AI-specific legislation. In October 2025, the government held a public engagement “sprint” in connection with a new AI Strategy Task Force to support a renewed national AI strategy, expected to rely on policy mechanisms rather than comprehensive legislative reform. Canada's Minister of Artificial Intelligence and Digital Innovation, Evan Solomon, stated that “Canada is scaling homegrown companies while also working with international partners to build the advanced infrastructure our innovators require.”&lt;/p&gt;

&lt;p&gt;This creates what might be called the corporate governance paradox: in the absence of binding regulation, corporations like Microsoft step into the gap with voluntary commitments, infrastructure investments, and self-imposed governance frameworks. Microsoft's five-point sovereignty plan, its Sovereign Landing Zone architecture, and its Threat Intelligence Hub all function as de facto governance mechanisms. But they are governance mechanisms designed, implemented, and enforced by the governed entity itself.&lt;/p&gt;

&lt;p&gt;The paradox deepens when you consider that Canada has launched the Canadian Artificial Intelligence Safety Institute (CAISI) as part of a broader C$2.4 billion investment in AI initiatives announced in the 2024 federal budget, alongside a C$2 billion Sovereign AI Compute Strategy encompassing the AI Compute Challenge (up to C$700 million), the Sovereign Compute Infrastructure Programme (up to C$705 million), and the AI Compute Access Fund (up to C$300 million). The country also has sector-specific regulatory efforts: the Office of the Superintendent of Financial Institutions (OSFI) has released Draft Guideline E-23 on Model Risk Management for financial institutions, Ontario's Workers for Workers Four Act (effective 2026) will impose requirements on employers using AI in hiring, and Canadian law societies in Alberta, British Columbia, and Ontario have issued guidance for lawyers using generative AI. But none of these measures constitute the kind of comprehensive, cross-sector AI governance framework that the EU AI Act represents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsible AI Tooling and the Measurement Problem
&lt;/h2&gt;

&lt;p&gt;Microsoft's responsible AI framework rests on six stated principles: fairness, reliability and safety, privacy and security, inclusiveness, transparency, and accountability. The company has operationalised these through its Responsible AI Standard, which covers six domains and establishes 14 goals intended to reduce AI risks and their associated harms. But principles are not outcomes. The critical question is whether Microsoft's tooling can produce measurable governance results that satisfy regulators, customers, and civil society stakeholders.&lt;/p&gt;

&lt;p&gt;The company's primary instrument is the Responsible AI Dashboard, which integrates several components for assessing and improving model performance. Error Analysis identifies cohorts of data with higher error rates, including when systems underperform for specific demographic groups or infrequently observed input conditions. Fairness Assessment, powered by the open-source Fairlearn library, identifies which groups may be disproportionately negatively impacted by an AI system and in what ways. Model Interpretability, powered by InterpretML, generates human-understandable descriptions of model predictions at both global and local levels; for example, it can explain what features affect the overall behaviour of a loan allocation model, or why a specific customer's application was approved or rejected. The dashboard also includes counterfactual what-if components that help stakeholders explore how changes in inputs would alter outcomes.&lt;/p&gt;

&lt;p&gt;For generative AI specifically, Microsoft Foundry allows developers to assess applications for quality and safety using both human review and AI-assisted metrics. Microsoft has also introduced Transparency Notes, documentation designed to help customers understand how AI technologies work and make informed deployment decisions. The company's 2025 Responsible AI Transparency Report detailed 67 red-teaming operations conducted across flagship models, including the Phi series and Copilot tools, stress-testing them for vulnerabilities to malicious prompts and misuse. Microsoft introduced an internal workflow tool that centralises responsible AI requirements and simplifies documentation for pre-deployment reviews; for high-impact or sensitive use cases involving biometric data or critical infrastructure, the company provides hands-on counselling to ensure heightened scrutiny and ethical alignment.&lt;/p&gt;

&lt;p&gt;In September 2025, Nadella announced new AI commitments focusing on enhanced safety protocols, transparency in algorithms, and investments in bias mitigation tools. He warned at the World Economic Forum that AI would lose public support unless it demonstrated tangible value: “We will quickly lose even the social permission to take something like energy, which is a scarce resource, and use it to generate these tokens, if these tokens are not improving health outcomes, education outcomes, public sector efficiency, private sector competitiveness.”&lt;/p&gt;

&lt;p&gt;Microsoft has also aligned its Cloud Adoption Framework AI governance guidance with the NIST AI Risk Management Framework (AI RMF), which organises recommendations into four core functions: Govern, Map, Measure, and Manage. Azure Policy and Microsoft Purview are offered as tools to enforce policies automatically across AI deployments, with regular assessments of areas where automation can improve policy adherence. Counterfit, an open-source command-line tool, allows developers to simulate cyberattacks against AI systems, assessing vulnerabilities across cloud, on-premises, and edge environments.&lt;/p&gt;

&lt;p&gt;Yet the measurement problem persists. Responsible AI dashboards and transparency notes are useful tools, but they are fundamentally self-assessment instruments. They tell you what Microsoft's own systems detect about Microsoft's own models. Civil society organisations have been explicit about what they consider insufficient. A survey by The Future Society of 44 civil society organisations found overwhelming consensus on the need for legally binding measures, with enforcement mechanisms receiving the highest support across all priorities. The top-ranked demand was establishing legally binding “red lines” prohibiting certain high-risk AI systems incompatible with human rights obligations, followed by mandating systematic, independent third-party audits of general-purpose AI systems covering bias, transparency, and accountability. A side event titled “Global AI Governance: Empowering Civil Society,” held during the Paris AI Action Summit in February 2025, reinforced these priorities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Frontier Governance Framework and Corporate Accountability
&lt;/h2&gt;

&lt;p&gt;Microsoft's response to growing calls for accountability has been its Frontier Governance Framework, introduced in the 2025 Transparency Report. The framework emerged from voluntary safety commitments made in May 2024 alongside fifteen other AI organisations and now functions as an internal monitoring and risk assessment mechanism for advanced models before release. It represents Microsoft's attempt to self-regulate frontier AI development before governments can impose external constraints.&lt;/p&gt;

&lt;p&gt;The framework's effectiveness depends entirely on its implementation rigour and the independence of its oversight. Microsoft's partnerships with civil society organisations, including its collaboration with the Stimson Center on the Global Perspectives Responsible AI Fellowship, suggest an awareness that corporate governance cannot operate in isolation. The fellowship brings together diverse stakeholders from civil society, academia, and the private sector for discussions on AI's societal impact. Brad Smith has emphasised that government, industry, academia, and civil society must work together to advance AI policy.&lt;/p&gt;

&lt;p&gt;But awareness is not the same as accountability. The gap between corporate voluntary commitments and the binding regulatory frameworks that civil society demands remains wide. As one participant in The Future Society consultation articulated: “Public accountability demands that we develop meaningful measures of impact on important issues like standards of living and be transparent about how things are going.” Civil society organisations are calling for standardised methodologies for independent verification across jurisdictions, crisis response protocols with clear intervention thresholds, and transparent participation mechanisms that ensure equitable representation. Microsoft's investment of US$80 billion in AI data centres during fiscal year 2025 makes it one of the world's largest investors in AI infrastructure; that scale of spending creates commensurate obligations for governance transparency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Divergent Frameworks and the Replicability Question
&lt;/h2&gt;

&lt;p&gt;The global landscape of AI governance is characterised by fundamental divergences. The EU has adopted a regulation-first approach emphasising human rights, conformity assessments, and mandatory transparency. The United States has historically favoured innovation-first self-governance, though sector regulators including the Consumer Financial Protection Bureau, the Food and Drug Administration, and the Equal Employment Opportunity Commission are increasingly referencing NIST AI RMF principles in their expectations for safe deployment. China pursues state-led AI governance with centralised control over AI development. The BRICS nations, representing eleven countries including Brazil, Russia, India, China, South Africa, Saudi Arabia, Egypt, the UAE, Ethiopia, Indonesia, and Iran, advocate for flexible governance structures that respect national sovereignty while maintaining international cooperation. McKinsey analysis suggests that sovereign AI could represent a market of US$600 billion by 2030, with up to 40% of AI workloads potentially moving to sovereign environments.&lt;/p&gt;

&lt;p&gt;Only about 30 countries currently host in-country compute infrastructure capable of supporting advanced AI workloads. Many lack not only hardware but also local model development, applications, energy systems, and governance frameworks optimised for AI. This compute divide creates a structural dependency: nations without indigenous AI infrastructure must rely on hyperscalers like Microsoft, accepting their governance frameworks as a condition of access to AI capabilities. Seventy-one per cent of executives, investors, and government officials surveyed by McKinsey characterised sovereign AI as an “existential concern” or “strategic imperative” for their organisations.&lt;/p&gt;

&lt;p&gt;Microsoft's Canadian investment can be seen as a template for this dynamic. The company offers sovereignty tools (SLZ, SAIL, Azure Local), cybersecurity collaboration (Threat Intelligence Hub), and local AI developer support (Cohere partnership). Cohere's advanced language models, including Command A, Embed 4, and Rerank, are being integrated into the Microsoft Foundry first-party model lineup, making Canadian-developed AI accessible on Azure. Microsoft and Cohere aim to co-develop industry-specific models for sectors like natural resources and manufacturing, where Canada has particular strengths. This partnership serves a dual purpose: it provides enterprise customers with an alternative to US-developed models, and it bolsters Canada's credentials as an AI innovation hub.&lt;/p&gt;

&lt;p&gt;The question of replicability hinges on whether Microsoft's approach can be transplanted to jurisdictions with fundamentally different regulatory, political, and economic contexts. Consider the EU: Microsoft has already committed to end-to-end AI data processing within Europe as part of the EU Data Boundary, and Microsoft 365 Copilot now processes interactions in-country for 15 countries. The company's Sovereign Landing Zone provides EU-specific policy sets aligned with the AI Act's requirements. But the EU's regulatory expectations go well beyond data residency. The Act requires conformity assessments for high-risk systems, detailed technical documentation, human oversight mechanisms, and ongoing monitoring obligations. These requirements demand independent verification, not just self-reported compliance through corporate dashboards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Governance That Outlasts the Press Release
&lt;/h2&gt;

&lt;p&gt;The mechanisms that would transform corporate AI commitments into measurable governance outcomes fall into three categories: explainability, auditability, and fairness documentation. Each requires specific institutional arrangements that go beyond voluntary corporate action.&lt;/p&gt;

&lt;p&gt;Explainability demands that AI systems provide meaningful explanations of their decisions to affected individuals. Microsoft's InterpretML and model interpretability tools offer technical capabilities for this, generating both global explanations (what features affect a model's overall behaviour) and local explanations (why a specific decision was made). But technical explainability is only useful if it is accessible to non-technical stakeholders, including regulators, affected communities, and individual users. The EU AI Act's transparency obligations under Article 50, applicable from August 2026, will require explanations that are comprehensible to the humans who interact with AI systems, not just the engineers who build them.&lt;/p&gt;

&lt;p&gt;Auditability requires independent third-party access to AI systems, training data, and deployment processes. Microsoft's red-teaming operations and its alignment with the NIST AI RMF's Govern, Map, Measure, and Manage functions provide an internal audit framework. But the civil society consensus, as documented by The Future Society, is that self-auditing is insufficient. Measurable governance outcomes require external audit mechanisms with genuine investigative authority, standardised methodologies for independent verification across jurisdictions, and enforceable penalties for non-compliance. The EU AI Act's conformity assessment procedures for high-risk systems point in this direction, but their effectiveness will depend on the capacity and independence of national competent authorities.&lt;/p&gt;

&lt;p&gt;Fairness documentation requires systematic evidence that AI systems do not discriminate against protected groups. Microsoft's Fairlearn library and the Responsible AI Dashboard's fairness assessment capabilities provide tools for detecting disparate impact. But fairness is not a purely technical concept. It involves normative judgements about which disparities are acceptable and which constitute discrimination, judgements that vary across cultures, legal systems, and political contexts. A fairness standard calibrated for Canadian employment law may be inadequate for EU anti-discrimination directives or for the complex intersectional discrimination patterns that civil society organisations have documented.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Replicable Governance Actually Requires
&lt;/h2&gt;

&lt;p&gt;Microsoft's Canadian investment demonstrates that a hyperscaler can build infrastructure, deploy sovereignty tools, and partner with local institutions to create governance capabilities. The skills component alone is substantial: Microsoft aims to help 250,000 Canadians earn AI credentials by 2026 through its Microsoft Elevate unit, having already engaged 5.7 million learners and supported 546,000 individuals in completing AI training across the country. Only 24% of Canadians have received AI-related training, compared to a 39% global average, according to Microsoft data.&lt;/p&gt;

&lt;p&gt;But replicable governance requires something more: institutional arrangements that survive changes in corporate leadership, shifts in commercial strategy, and the inevitable tensions between profitability and public interest.&lt;/p&gt;

&lt;p&gt;Nadella himself has acknowledged this tension. In November 2025, he published a widely circulated memo on “Shared Economic Gains,” warning the tech industry against value extraction and arguing that for the AI revolution to be sustainable, it must create more wealth for its users than for its creators. He has consistently argued that “technology development doesn't just happen; it happens because us humans make design choices. Those design choices need to be grounded in principles and ethics.”&lt;/p&gt;

&lt;p&gt;The replicability question ultimately comes down to whether Microsoft's governance architecture can be separated from Microsoft itself. If the Sovereign AI Landing Zone is truly open-source, if the Threat Intelligence Hub's methodologies can be adopted by other nations' cybersecurity centres, if the responsible AI tooling can be validated by independent auditors, then Canada's experience could serve as a genuine template. If, however, these governance mechanisms remain dependent on Microsoft's infrastructure, subject to Microsoft's terms of service, and validated primarily by Microsoft's own assessments, then they represent corporate governance rather than public governance, and their replicability is limited to jurisdictions willing to accept that distinction.&lt;/p&gt;

&lt;p&gt;The EU AI Act's phased implementation will provide the most rigorous test. By August 2026, when the majority of provisions become applicable, Microsoft and every other AI provider operating in Europe will face mandatory requirements for transparency, explainability, and accountability that no voluntary framework can substitute. The question is whether the governance muscles Microsoft is building in Canada, through its SLZ architecture, its Threat Intelligence Hub, and its responsible AI tooling, will prove strong enough to meet those requirements, or whether the gap between corporate self-governance and democratic accountability will prove too wide to bridge.&lt;/p&gt;

&lt;p&gt;For Canada, for Europe, and for the approximately 30 nations currently capable of hosting advanced AI workloads, the answer will define the next decade of AI governance. Microsoft has laid down a US$5.4 billion wager that its version of sovereignty by design can become the global standard. Whether that wager pays off depends not on the size of the investment, but on whether the governance frameworks it produces can earn the trust of the regulators, civil society organisations, and citizens whose lives AI systems increasingly shape.&lt;/p&gt;




&lt;h2&gt;
  
  
  References and Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Microsoft. “Microsoft Deepens Its Commitment to Canada with Landmark $19B AI Investment.” Microsoft On the Issues, 9 December 2025. &lt;a href="https://blogs.microsoft.com/on-the-issues/2025/12/09/microsoft-deepens-its-commitment-to-canada-with-landmark-19b-ai-investment/" rel="noopener noreferrer"&gt;https://blogs.microsoft.com/on-the-issues/2025/12/09/microsoft-deepens-its-commitment-to-canada-with-landmark-19b-ai-investment/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Business Standard. “Microsoft to invest over $5.4 bn in Canada to expand AI infrastructure.” 9 December 2025. &lt;a href="https://www.business-standard.com/technology/tech-news/microsoft-to-invest-over-5-4-bn-in-canada-to-expand-ai-infrastructure-125120901025_1.html" rel="noopener noreferrer"&gt;https://www.business-standard.com/technology/tech-news/microsoft-to-invest-over-5-4-bn-in-canada-to-expand-ai-infrastructure-125120901025_1.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fortune Business Insights. “Sovereign Cloud Market Size, Share, Growth | Forecast [2034].” 2025. &lt;a href="https://www.fortunebusinessinsights.com/sovereign-cloud-market-112386" rel="noopener noreferrer"&gt;https://www.fortunebusinessinsights.com/sovereign-cloud-market-112386&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;EU Artificial Intelligence Act. “Implementation Timeline.” 2025. &lt;a href="https://artificialintelligenceact.eu/implementation-timeline/" rel="noopener noreferrer"&gt;https://artificialintelligenceact.eu/implementation-timeline/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft Learn. “Sovereign Landing Zone (SLZ) Implementation Options.” 2025. &lt;a href="https://learn.microsoft.com/en-us/industry/sovereign-cloud/sovereign-public-cloud/sovereign-landing-zone/implementation-options" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/industry/sovereign-cloud/sovereign-public-cloud/sovereign-landing-zone/implementation-options&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft Azure Blog. “Microsoft Strengthens Sovereign Cloud Capabilities with New Services.” November 2025. &lt;a href="https://azure.microsoft.com/en-us/blog/microsoft-strengthens-sovereign-cloud-capabilities-with-new-services/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/blog/microsoft-strengthens-sovereign-cloud-capabilities-with-new-services/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Innovation, Science and Economic Development Canada. “Artificial Intelligence and Data Act.” &lt;a href="https://ised-isde.canada.ca/site/innovation-better-canada/en/artificial-intelligence-and-data-act" rel="noopener noreferrer"&gt;https://ised-isde.canada.ca/site/innovation-better-canada/en/artificial-intelligence-and-data-act&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;White &amp;amp; Case LLP. “AI Watch: Global Regulatory Tracker, Canada.” 2025. &lt;a href="https://www.whitecase.com/insight-our-thinking/ai-watch-global-regulatory-tracker-canada" rel="noopener noreferrer"&gt;https://www.whitecase.com/insight-our-thinking/ai-watch-global-regulatory-tracker-canada&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft. “Responsible AI Principles and Approach.” &lt;a href="https://www.microsoft.com/en-us/ai/principles-and-approach" rel="noopener noreferrer"&gt;https://www.microsoft.com/en-us/ai/principles-and-approach&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft Learn. “What is Responsible AI, Azure Machine Learning.” &lt;a href="https://learn.microsoft.com/en-us/azure/machine-learning/concept-responsible-ai?view=azureml-api-2" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/azure/machine-learning/concept-responsible-ai?view=azureml-api-2&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GitHub. “Microsoft Responsible AI Toolbox.” &lt;a href="https://github.com/microsoft/responsible-ai-toolbox" rel="noopener noreferrer"&gt;https://github.com/microsoft/responsible-ai-toolbox&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI Magazine. “Inside Microsoft's 2025 Responsible AI Transparency Report.” 2025. &lt;a href="https://aimagazine.com/articles/inside-microsofts-2025-responsible-ai-transparency-report" rel="noopener noreferrer"&gt;https://aimagazine.com/articles/inside-microsofts-2025-responsible-ai-transparency-report&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Future Society. “Ten AI Governance Priorities: Survey of 44 Civil Society Organizations.” 2025. &lt;a href="https://thefuturesociety.org/cso-ai-governance-priorities/" rel="noopener noreferrer"&gt;https://thefuturesociety.org/cso-ai-governance-priorities/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;McKinsey &amp;amp; Company. “The Sovereign AI Agenda: Moving from Ambition to Reality.” 2025. &lt;a href="https://www.mckinsey.com/capabilities/tech-and-ai/our-insights/tech-forward/the-sovereign-ai-agenda-moving-from-ambition-to-reality" rel="noopener noreferrer"&gt;https://www.mckinsey.com/capabilities/tech-and-ai/our-insights/tech-forward/the-sovereign-ai-agenda-moving-from-ambition-to-reality&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NIST. “AI Risk Management Framework.” &lt;a href="https://www.nist.gov/itl/ai-risk-management-framework" rel="noopener noreferrer"&gt;https://www.nist.gov/itl/ai-risk-management-framework&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft Learn. “Govern AI, Cloud Adoption Framework.” &lt;a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/ai/govern" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/ai/govern&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ERP Today. “Microsoft's Canada Investment Puts Digital Sovereignty to Work.” December 2025. &lt;a href="https://erp.today/microsofts-canada-investment-puts-digital-sovereignty-to-work/" rel="noopener noreferrer"&gt;https://erp.today/microsofts-canada-investment-puts-digital-sovereignty-to-work/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BetaKit. “Microsoft to spend $7.5 billion on AI data centre expansion with pledge to protect Canada's 'digital sovereignty.'” December 2025. &lt;a href="https://betakit.com/microsoft-to-spend-7-5-billion-on-ai-data-centre-expansion-with-pledge-to-protect-canadas-digital-sovereignty/" rel="noopener noreferrer"&gt;https://betakit.com/microsoft-to-spend-7-5-billion-on-ai-data-centre-expansion-with-pledge-to-protect-canadas-digital-sovereignty/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BNN Bloomberg. “Microsoft will protect Canada digital sovereignty: president.” 13 December 2025. &lt;a href="https://www.bnnbloomberg.ca/business/politics/2025/12/13/microsoft-president-insists-company-will-stand-up-to-defend-canadian-digital-sovereignty/" rel="noopener noreferrer"&gt;https://www.bnnbloomberg.ca/business/politics/2025/12/13/microsoft-president-insists-company-will-stand-up-to-defend-canadian-digital-sovereignty/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trilateral Research. “EU AI Act Compliance Timeline: Key Dates for 2025-2027 by Risk Tier.” 2025. &lt;a href="https://trilateralresearch.com/responsible-ai/eu-ai-act-implementation-timeline-mapping-your-models-to-the-new-risk-tiers" rel="noopener noreferrer"&gt;https://trilateralresearch.com/responsible-ai/eu-ai-act-implementation-timeline-mapping-your-models-to-the-new-risk-tiers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tony Blair Institute for Global Change. “Sovereignty in the Age of AI: Strategic Choices, Structural Dependencies and the Long Game Ahead.” 2025. &lt;a href="https://institute.global/insights/tech-and-digitalisation/sovereignty-in-the-age-of-ai-strategic-choices-structural-dependencies" rel="noopener noreferrer"&gt;https://institute.global/insights/tech-and-digitalisation/sovereignty-in-the-age-of-ai-strategic-choices-structural-dependencies&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TechXplore. “Microsoft's AI deal promises Canada digital sovereignty, but is that a pledge it can keep?” January 2026. &lt;a href="https://techxplore.com/news/2026-01-microsoft-ai-canada-digital-sovereignty.html" rel="noopener noreferrer"&gt;https://techxplore.com/news/2026-01-microsoft-ai-canada-digital-sovereignty.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Canada.ca. “Canada's National Cyber Security Strategy: Securing Canada's Digital Future.” 2025. &lt;a href="https://www.publicsafety.gc.ca/cnt/rsrcs/pblctns/ntnl-cbr-scrt-strtg-2025/index-en.aspx" rel="noopener noreferrer"&gt;https://www.publicsafety.gc.ca/cnt/rsrcs/pblctns/ntnl-cbr-scrt-strtg-2025/index-en.aspx&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Osler, Hoskin &amp;amp; Harcourt LLP. “Canada's 2026 Privacy Priorities: Data Sovereignty, Open Banking and AI.” 2025. &lt;a href="https://www.osler.com/en/insights/reports/2025-legal-outlook/canadas-2026-privacy-priorities-data-sovereignty-open-banking-and-ai/" rel="noopener noreferrer"&gt;https://www.osler.com/en/insights/reports/2025-legal-outlook/canadas-2026-privacy-priorities-data-sovereignty-open-banking-and-ai/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CNBC. “Microsoft expects to spend $80 billion on AI-enabled data centers in fiscal 2025.” 3 January 2025. &lt;a href="https://www.cnbc.com/2025/01/03/microsoft-expects-to-spend-80-billion-on-ai-data-centers-in-fy-2025.html" rel="noopener noreferrer"&gt;https://www.cnbc.com/2025/01/03/microsoft-expects-to-spend-80-billion-on-ai-data-centers-in-fy-2025.html&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft 365 Blog. “Microsoft offers in-country data processing to 15 countries to strengthen sovereign controls for Microsoft 365 Copilot.” 4 November 2025. &lt;a href="https://www.microsoft.com/en-us/microsoft-365/blog/2025/11/04/microsoft-offers-in-country-data-processing-to-15-countries-to-strengthen-sovereign-controls-for-microsoft-365-copilot/" rel="noopener noreferrer"&gt;https://www.microsoft.com/en-us/microsoft-365/blog/2025/11/04/microsoft-offers-in-country-data-processing-to-15-countries-to-strengthen-sovereign-controls-for-microsoft-365-copilot/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft. “Responsible AI Tools and Practices.” &lt;a href="https://www.microsoft.com/en-us/ai/tools-practices" rel="noopener noreferrer"&gt;https://www.microsoft.com/en-us/ai/tools-practices&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Schwartz Reisman Institute, University of Toronto. “What's Next After AIDA?” 2025. &lt;a href="https://srinstitute.utoronto.ca/news/whats-next-for-aida" rel="noopener noreferrer"&gt;https://srinstitute.utoronto.ca/news/whats-next-for-aida&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Digital Journal. “Microsoft's $19-billion Canadian AI investment stokes digital sovereignty debate.” December 2025. &lt;a href="https://www.digitaljournal.com/business/microsofts-19-billion-canadian-ai-investment-stokes-digital-sovereignty-debate/article" rel="noopener noreferrer"&gt;https://www.digitaljournal.com/business/microsofts-19-billion-canadian-ai-investment-stokes-digital-sovereignty-debate/article&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft Source EMEA. “Microsoft Expands Digital Sovereignty Capabilities.” November 2025. &lt;a href="https://news.microsoft.com/source/emea/2025/11/microsoft-expands-digital-sovereignty-capabilities/" rel="noopener noreferrer"&gt;https://news.microsoft.com/source/emea/2025/11/microsoft-expands-digital-sovereignty-capabilities/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fos7pdncawa0mgqcin0gf.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%2Fos7pdncawa0mgqcin0gf.png" alt="Tim Green" width="100" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tim Green&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;UK-based Systems Theorist &amp;amp; Independent Technology Writer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Tim explores the intersections of artificial intelligence, decentralised cognition, and posthuman ethics. His work, published at &lt;a href="https://smarterarticles.co.uk" rel="noopener noreferrer"&gt;smarterarticles.co.uk&lt;/a&gt;, challenges dominant narratives of technological progress while proposing interdisciplinary frameworks for collective intelligence and digital stewardship.&lt;/p&gt;

&lt;p&gt;His writing has been featured on Ground News and shared by independent researchers across both academic and technological communities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ORCID:&lt;/strong&gt; &lt;a href="https://orcid.org/0009-0002-0156-9795" rel="noopener noreferrer"&gt;0009-0002-0156-9795&lt;/a&gt; &lt;br&gt;
&lt;strong&gt;Email:&lt;/strong&gt; &lt;a href="mailto:tim@smarterarticles.co.uk"&gt;tim@smarterarticles.co.uk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>humanintheloop</category>
      <category>digitalsovereignty</category>
      <category>aicorporategovernance</category>
      <category>sovereigncloud</category>
    </item>
    <item>
      <title>Pre-Code Planning Stopped Me From Getting Stuck on a 3-Hour ETL Pipeline</title>
      <dc:creator>Yaw Opoku Mensah Baffoe</dc:creator>
      <pubDate>Sun, 31 May 2026 10:55:25 +0000</pubDate>
      <link>https://dev.to/yaw_baffoe/pre-code-planning-stopped-me-from-getting-stuck-on-a-3-hour-etl-pipeline-2922</link>
      <guid>https://dev.to/yaw_baffoe/pre-code-planning-stopped-me-from-getting-stuck-on-a-3-hour-etl-pipeline-2922</guid>
      <description>&lt;p&gt;I recently finished building a multi-channel data pipeline to solve a specific problem: consolidating fragmented monthly sales data from an in-store till, Uber Eats, and Deliveroo into a single master source for Looker Studio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://datastudio.google.com/reporting/c54dd374-fe50-45c5-a88b-d4fd22aafdad" rel="noopener noreferrer"&gt;My Dashboard&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The technical work took me slightly under 3 hours to build. But the biggest takeaway for me wasn't the speed, it was the shift in how I approached the build.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with "Figuring it out as you go"
&lt;/h2&gt;

&lt;p&gt;On previous projects, my default habit was to open a blank IDE and just start typing. I’d try to figure out the data schemas and transformations while mid script.&lt;/p&gt;

&lt;p&gt;When I did that, I ended up hitting a wall. I’d confuse myself, lose track of the data flow, and get stuck in a loop of debugging things I hadn't fully defined yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Did Differently This Time
&lt;/h2&gt;

&lt;p&gt;Before touching a single line of Python for this dashboard, I forced myself to properly define the parameters of the project in a document:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The Exact Inputs: Mapping out the column mismatches between the three different CSV exports (Till vs. Uber vs. Deliveroo).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Exact Transformation Steps: Deciding how to handle commission deductions and currency formatting before writing the cleaning functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Destination: Defining how the final master source needed to be structured for Looker Studio to read it cleanly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;Because the blueprint was already written, the actual coding process was just pure execution. I stayed hyper-focused for the full 3 hours because there was zero guesswork involved.&lt;/p&gt;

&lt;p&gt;It showed me that my biggest bottleneck usually isn't my technical ability or my understanding of code; it's the framework I use to approach a problem. Spending time upfront to structure the data pipeline logically turned the coding phase into a straightforward task rather than a guessing game.&lt;/p&gt;

&lt;p&gt;For anyone else working through data projects or personal builds: if you find yourself constantly hitting mental blocks mid code, try closing the IDE and explicitly defining the data flow first. It saves a massive amount of cognitive energy.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>data</category>
      <category>dataengineering</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Cómo solucionar `OSError: [Errno 13] Permission denied` al usar `pip install`</title>
      <dc:creator>Erick Eduardo Ramos</dc:creator>
      <pubDate>Sun, 31 May 2026 10:53:42 +0000</pubDate>
      <link>https://dev.to/erickeduardoramos03/como-solucionar-oserror-errno-13-permission-denied-al-usar-pip-install-1hmm</link>
      <guid>https://dev.to/erickeduardoramos03/como-solucionar-oserror-errno-13-permission-denied-al-usar-pip-install-1hmm</guid>
      <description>&lt;h1&gt;
  
  
  Cómo solucionar &lt;code&gt;OSError: [Errno 13] Permission denied&lt;/code&gt; al usar &lt;code&gt;pip install&lt;/code&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ¿Por qué ocurre este error?
&lt;/h2&gt;

&lt;p&gt;El error ocurre porque &lt;code&gt;pip&lt;/code&gt; intenta instalar paquetes en un directorio del sistema (como &lt;code&gt;/usr/local/lib/python2.7/dist-packages/&lt;/code&gt;) que requiere permisos de administrador (&lt;code&gt;root&lt;/code&gt;). Esto sucede cuando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estás usando el &lt;code&gt;pip&lt;/code&gt; del sistema operativo (no el de un entorno virtual)&lt;/li&gt;
&lt;li&gt;El sistema tiene configurado Python y pip para instalar globalmente en directorios protegidos&lt;/li&gt;
&lt;li&gt;Estás ejecutando &lt;code&gt;pip&lt;/code&gt; sin los permisos necesarios, o sin usar &lt;code&gt;sudo&lt;/code&gt; (que &lt;strong&gt;no es recomendable&lt;/strong&gt; por seguridad)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pasos para solucionarlo definitivamente
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ✅ Solución recomendada: Usa entornos virtuales (vía &lt;code&gt;venv&lt;/code&gt; o &lt;code&gt;conda&lt;/code&gt;)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Crea un entorno virtual aislado
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="c"&gt;# o si usas Python 2 (no recomendado, pero posible):&lt;/span&gt;
&lt;span class="c"&gt;# virtualenv venv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Activa el entorno
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
&lt;span class="c"&gt;# En Windows: venv\Scripts\activate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Instala las dependencias dentro del entorno
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;Ventaja&lt;/strong&gt;: No necesitas &lt;code&gt;sudo&lt;/code&gt;, no contaminas el sistema, y cada proyecto tiene sus propias dependencias.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ⚠️ Solución alternativa (solo si NO puedes usar entornos virtuales)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Opción A: Instala solo para el usuario actual (sin &lt;code&gt;sudo&lt;/code&gt;)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Esto instala en &lt;code&gt;~/.local/lib/...&lt;/code&gt;, evitando permisos de sistema.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Opción B: Cambia los permisos del directorio (riesgoso)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt;:&lt;span class="nv"&gt;$USER&lt;/span&gt; /usr/local/lib/python2.7/dist-packages/
&lt;span class="c"&gt;# O más seguro:&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt;:&lt;span class="nv"&gt;$USER&lt;/span&gt; /usr/local/lib/python3.x/dist-packages/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Advertencia&lt;/strong&gt;: Esto puede romper la gestión de paquetes del sistema operativo (especialmente en Debian/Ubuntu).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Bloque de código corregido (ejemplo práctico)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Crear entorno virtual&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv django-env

&lt;span class="c"&gt;# 2. Activar entorno&lt;/span&gt;
&lt;span class="nb"&gt;source &lt;/span&gt;django-env/bin/activate

&lt;span class="c"&gt;# 3. Actualizar pip (opcional pero recomendado)&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip

&lt;span class="c"&gt;# 4. Instalar dependencias&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Pro-tip: Evita &lt;code&gt;sudo pip install&lt;/code&gt; a toda costa
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Riesgo de seguridad&lt;/strong&gt;: Ejecutas código no verificado como &lt;code&gt;root&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conflicto con el gestor de paquetes del sistema&lt;/strong&gt;: &lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;yum&lt;/code&gt;, etc., pueden romperse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dificultad para reproducir entornos&lt;/strong&gt;: Las instalaciones globales se vuelven caóticas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ &lt;strong&gt;Mejor práctica&lt;/strong&gt;: Usa &lt;code&gt;venv&lt;/code&gt; + &lt;code&gt;pip install&lt;/code&gt; sin privilegios.&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Para producción&lt;/strong&gt;: Usa contenedores Docker o sistemas como &lt;code&gt;pipenv&lt;/code&gt;/&lt;code&gt;poetry&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Nota histórica&lt;/strong&gt;: El error muestra Python 2.7. &lt;strong&gt;Python 2 está obsoleto desde 2020&lt;/strong&gt;. Migrar a Python 3 es obligatorio para seguridad y soporte.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>beginners</category>
      <category>python</category>
      <category>spanish</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>From Smart Contract Hell to JavaScript Solace: Building ArdhiChain for a 36-Hour Hackathon</title>
      <dc:creator>Benjamin Koimett</dc:creator>
      <pubDate>Sun, 31 May 2026 10:53:14 +0000</pubDate>
      <link>https://dev.to/bwanachairman/from-smart-contract-hell-to-javascript-solace-building-ardhichain-for-a-36-hour-hackathon-1cnk</link>
      <guid>https://dev.to/bwanachairman/from-smart-contract-hell-to-javascript-solace-building-ardhichain-for-a-36-hour-hackathon-1cnk</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&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;From&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Smart&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Contract&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Hell&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;JavaScript&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Solace:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Building&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ArrdhiChain&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;36-Hour&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Hackathon"&lt;/span&gt;
&lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;How&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;survived&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Polygon&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Amoy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;testnet&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;failures,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;gas&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;estimation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;nightmares,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Friday&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PM&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;MVP&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;deadline&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;finding&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;peace&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;vanilla&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;JavaScript&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;optimistic&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;UI."&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;web3&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;hackathon&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;javascript&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;polygon&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;solidity&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;devjournal&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In the beginning...
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Timeline:&lt;/strong&gt; Thursday 8 AM to Friday 5 PM MVP deadline. Pitches started Friday 11 AM (yes, while I was still debugging).&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Sanity level:&lt;/strong&gt; Negative.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Shipped. Barely.&lt;/p&gt;

&lt;p&gt;This past Thursday to Friday wasn't a 72-hour marathon. It was a &lt;strong&gt;36-hour sprint&lt;/strong&gt; where the smart contracts tried to break me, the Polygon Amoy testnet played games, and JavaScript became my unexpected sanctuary.&lt;/p&gt;

&lt;p&gt;Here's the raw, unfiltered story of building &lt;strong&gt;ArrdhiChain&lt;/strong&gt; - a web3 dApp - under hackathon conditions that felt designed to cause panic attacks.&lt;/p&gt;


&lt;h2&gt;
  
  
  Thursday Morning: The Overconfidence Phase
&lt;/h2&gt;

&lt;p&gt;The hackathon kicked off Thursday at 8 AM. MVP needed by &lt;strong&gt;Friday 5 PM&lt;/strong&gt;. Pitches started &lt;strong&gt;Friday 11 AM&lt;/strong&gt; (meaning the judges would be circulating while I was still patching bugs).&lt;/p&gt;

&lt;p&gt;My idea: A decentralized app on &lt;strong&gt;Polygon Amoy testnet&lt;/strong&gt; where users could interact with a custom smart contract. Simple. Elegant. Wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thursday 9 AM:&lt;/strong&gt; Smart contracts written in Solidity. Compiled flawlessly. I felt invincible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thursday 10 AM:&lt;/strong&gt; First deployment attempt. &lt;strong&gt;FAIL&lt;/strong&gt;. Gas estimation errors. Network timeouts. MetaMask crying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thursday 11 AM:&lt;/strong&gt; Discovered I was on Mumbai testnet, not Amoy. Two hours gone. Classic.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lesson #1:&lt;/strong&gt; The network dropdown is not your enemy. Ignoring it is.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Thursday 2 PM:&lt;/strong&gt; Finally got the contract live on Amoy:&lt;br&gt;&lt;br&gt;
🔗 &lt;a href="https://amoy.polygonscan.com/address/0xYOUR_CONTRACT_ADDRESS" rel="noopener noreferrer"&gt;&lt;code&gt;0xYOUR_CONTRACT_ADDRESS&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I celebrated with cold coffee. Too soon.&lt;/p&gt;


&lt;h2&gt;
  
  
  Thursday Night: The Web3 Integration Nightmare
&lt;/h2&gt;

&lt;p&gt;By Thursday evening, the contract was verified. But connecting it to the frontend was a special kind of torture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ethers.js v5 vs v6 conflicts&lt;/strong&gt; - two hours of Stack Overflow archaeology&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WalletConnect dropping sessions&lt;/strong&gt; every third refresh&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React state + async blockchain calls&lt;/strong&gt; creating race conditions I didn't even know existed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every transaction took 30 to 45 seconds. Users would see "Pending..." and close the tab. In a hackathon with judges walking the floor by Friday 11 AM, that's a death sentence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thursday midnight:&lt;/strong&gt; I pushed broken code to GitHub and stared at my ceiling for an hour. The MVP deadline was 17 hours away.&lt;/p&gt;


&lt;h2&gt;
  
  
  Friday Morning: Panic, Then Solace
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Friday 7 AM:&lt;/strong&gt; Coffee IV drip engaged. Judges would arrive in 4 hours. The contract worked on the backend, but the frontend was unusable.&lt;/p&gt;

&lt;p&gt;Then I made a decision that saved the project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Stop fighting the blockchain. Fall in love with the frontend.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I stripped the complexity. Hard.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Built a Mock Provider Fallback
&lt;/h3&gt;

&lt;p&gt;If MetaMask wasn't detected or the network was wrong, the UI gracefully fell back to a &lt;strong&gt;read-only mode&lt;/strong&gt;. Users could still see contract data, explore features, and understand the app - even if they couldn't transact yet.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Optimistic UI with Local Cache
&lt;/h3&gt;

&lt;p&gt;Even if a transaction took 30 seconds, the UI updated &lt;strong&gt;instantly&lt;/strong&gt;. I stored pending transactions in localStorage, showed a "confirming..." badge, and synced with the blockchain in the background.&lt;/p&gt;

&lt;p&gt;Users &lt;em&gt;felt&lt;/em&gt; speed. That's the JavaScript superpower.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Transaction State Machine with useReducer
&lt;/h3&gt;

&lt;p&gt;No more scattered &lt;code&gt;isLoading&lt;/code&gt; flags across 12 components. One clean reducer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// show form&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// show spinner + optimistic data&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// show confirmation + clear cache&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;// show friendly retry button&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Friday 10:30 AM - MVP Ready
&lt;/h3&gt;

&lt;p&gt;Thirty minutes before judges started walking the floor. The contract was live. The UI was responsive. And users could actually &lt;em&gt;use&lt;/em&gt; it without throwing their phones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Friday 11 AM:&lt;/strong&gt; Pitches began. I demoed ArrdhiChain with a smile. The backend was held together with duct tape and hope, but the frontend &lt;strong&gt;shipped&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Actually Shipped
&lt;/h2&gt;

&lt;p&gt;✅ Smart contract live on &lt;strong&gt;Polygon Amoy Testnet&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ Verified contract on Amoy Polygonscan&lt;br&gt;&lt;br&gt;
✅ React frontend with read-only fallback&lt;br&gt;&lt;br&gt;
✅ Optimistic UI + localStorage transaction cache&lt;br&gt;&lt;br&gt;
✅ "Solace Mode" toggle - disables writes, keeps UI butter-smooth  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live demo (Amoy):&lt;/strong&gt; [&lt;a href="https://land-ledge-git-frontend-benjie-bkoimetts-projects.vercel.app/dashboard" rel="noopener noreferrer"&gt;https://land-ledge-git-frontend-benjie-bkoimetts-projects.vercel.app/dashboard&lt;/a&gt;] &lt;br&gt;
&lt;strong&gt;Contract:&lt;/strong&gt; &lt;a href="https://amoy.polygonscan.com/address/0xYourAddress" rel="noopener noreferrer"&gt;&lt;code&gt;0xYourAddress&lt;/code&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; [&lt;a href="https://github.com/bkoimett/land-ledge.git" rel="noopener noreferrer"&gt;https://github.com/bkoimett/land-ledge.git&lt;/a&gt;]&lt;/p&gt;

&lt;h2&gt;
  
  
  From Smart Contract Hell to JavaScript Solace: Building ArrdhiChain for a 36-Hour Hackathon
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Hard Truth About Hackathon Web3
&lt;/h2&gt;

&lt;p&gt;Building a dApp in &lt;strong&gt;36 hours&lt;/strong&gt; is not development. It's survival.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smart contracts will compile but fail to deploy.&lt;/li&gt;
&lt;li&gt;Testnets will lie about gas fees.&lt;/li&gt;
&lt;li&gt;MetaMask will betray you at the worst moment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But JavaScript? JavaScript is &lt;strong&gt;home&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When the blockchain is slow, the frontend can be fast.&lt;br&gt;&lt;br&gt;
When transactions fail, the UI can recover.&lt;br&gt;&lt;br&gt;
When judges are watching, a smooth demo beats a perfect contract.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lesson #2:&lt;/strong&gt; In a hackathon, the user experience is the product. The blockchain is just the backend.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What I'd Do Differently (And What I'm Keeping)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Next time:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with the frontend mock first, add web3 later&lt;/li&gt;
&lt;li&gt;Use Wagmi or useDapp instead of raw ethers.js&lt;/li&gt;
&lt;li&gt;Test the &lt;em&gt;entire&lt;/em&gt; transaction flow before writing a single line of Solidity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I'm keeping:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimistic UI always&lt;/li&gt;
&lt;li&gt;LocalStorage as a transaction journal&lt;/li&gt;
&lt;li&gt;The "Solace Mode" pattern - read-only fallbacks for every web3 app&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;The hackathon didn't end at Friday 5 PM. But by then, I had shipped. The judges saw a working product. Users saw a smooth interface. And I learned that web3 stress is real - but JavaScript is where peace lives.&lt;/p&gt;

&lt;p&gt;If you're building a dApp under a deadline, remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;await&lt;/code&gt; is a suggestion, not a guarantee&lt;/li&gt;
&lt;li&gt;The frontend is where users live&lt;/li&gt;
&lt;li&gt;A well-placed &lt;code&gt;try/catch&lt;/code&gt; is sometimes more valuable than a perfect contract&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And when the blockchain breaks your heart, JavaScript will still be there.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Have you ever survived a web3 hackathon? What saved you - better planning or a last-minute frontend miracle? Drop your war stories below.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  web3 #hackathon #javascript #polygon #solidity #buildinpublic #devjournal
&lt;/h1&gt;

</description>
      <category>web3</category>
      <category>hackathon</category>
      <category>javascript</category>
      <category>ai</category>
    </item>
    <item>
      <title>I built a browser number strategy game where arithmetic becomes board control</title>
      <dc:creator>love mars</dc:creator>
      <pubDate>Sun, 31 May 2026 10:52:32 +0000</pubDate>
      <link>https://dev.to/love_mars_697691a3a1c44ba/i-built-a-browser-number-strategy-game-where-arithmetic-becomes-board-control-2gbg</link>
      <guid>https://dev.to/love_mars_697691a3a1c44ba/i-built-a-browser-number-strategy-game-where-arithmetic-becomes-board-control-2gbg</guid>
      <description>&lt;h2&gt;
  
  
  The idea
&lt;/h2&gt;

&lt;p&gt;Most math games feel like timed quizzes: answer fast, move on, repeat.&lt;/p&gt;

&lt;p&gt;I wanted to build something with a different texture. In &lt;strong&gt;Number Duel&lt;/strong&gt;, arithmetic is not the homework you do before the fun starts. It is the move system.&lt;/p&gt;

&lt;p&gt;You pick numbers to shape the board, limit your opponent, and set up future threats. The math is simple enough to play immediately, but the choices start to feel surprisingly tactical.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Each player has an &lt;strong&gt;active number&lt;/strong&gt; from 0 to 9.&lt;/p&gt;

&lt;p&gt;On a turn, the two active numbers combine to create a target. You claim the matching cell on a 5x5 board. Connect four cells in a row to win.&lt;/p&gt;

&lt;p&gt;For example, in &lt;strong&gt;Sum Duel&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I pick &lt;code&gt;9&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You pick &lt;code&gt;3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The target becomes &lt;code&gt;12&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The player whose turn it is can claim a &lt;code&gt;12&lt;/code&gt; cell&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting part is that your number does not only create your own move. It also controls what your opponent can do next.&lt;/p&gt;

&lt;p&gt;That shared constraint is where the strategy lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three modes are live
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Sum Duel&lt;/strong&gt; is the most approachable mode. Active numbers are added together, so the board is easy to read and the tactics are about timing, blocking, and forcing useful totals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product Duel&lt;/strong&gt; makes the board spikier. Multiplication creates repeated targets, unreachable zones, and more dramatic tempo swings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fifteen Duel&lt;/strong&gt; is a smaller puzzle mode using the numbers 1-9. First to claim three numbers that sum to 15 wins. The hidden trick: the eight winning triples are exactly the rows, columns, and diagonals of the 3x3 magic square, so the mode is secretly tic-tac-toe in disguise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hardest problem was onboarding
&lt;/h2&gt;

&lt;p&gt;The game logic was not the hard part.&lt;/p&gt;

&lt;p&gt;The hard part was getting the rules to click before a new player bounced.&lt;/p&gt;

&lt;p&gt;I tried to make the first screen do most of the teaching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Put the board front and center&lt;/li&gt;
&lt;li&gt;Highlight legal cells so players do not need to calculate every option&lt;/li&gt;
&lt;li&gt;Keep the first match short with a 5x5 board and connect-four win condition&lt;/li&gt;
&lt;li&gt;Move deeper strategy notes out of the way until players actually want them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am still tuning this. If you try the game, the feedback I care about most is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At what moment did the rules click?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;p&gt;The app is built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React + Vite&lt;/strong&gt; for the browser client&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare Workers&lt;/strong&gt; for the API surface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Durable Objects&lt;/strong&gt; for real-time multiplayer rooms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare D1&lt;/strong&gt; for daily challenge results and leaderboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Durable Objects turned out to be a nice fit for this shape of game.&lt;/p&gt;

&lt;p&gt;Each room maps to a single object instance. WebSocket connections stay in memory, the room owns the authoritative state, and important state can be persisted without running a separate game server.&lt;/p&gt;

&lt;p&gt;For a side project, that tradeoff has been pleasant: small deployment surface, real-time rooms, and no always-on server to babysit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;No signup, no ads, and it works on mobile:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://numberduel.mathmindpuzzles.com/" rel="noopener noreferrer"&gt;https://numberduel.mathmindpuzzles.com/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Strategy notes:&lt;br&gt;
&lt;a href="https://numberduel.mathmindpuzzles.com/strategy/" rel="noopener noreferrer"&gt;https://numberduel.mathmindpuzzles.com/strategy/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Magic square explainer:&lt;br&gt;
&lt;a href="https://numberduel.mathmindpuzzles.com/math/magic-square-15/" rel="noopener noreferrer"&gt;https://numberduel.mathmindpuzzles.com/math/magic-square-15/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback is very welcome, especially on first-time clarity and whether the game feels more like a puzzle or a duel.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>gamedev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Public WiFi in 2026: What's Actually Risky and What Isn't</title>
      <dc:creator>ricco020</dc:creator>
      <pubDate>Sun, 31 May 2026 10:47:46 +0000</pubDate>
      <link>https://dev.to/ricco020/public-wifi-in-2026-whats-actually-risky-and-what-isnt-4an5</link>
      <guid>https://dev.to/ricco020/public-wifi-in-2026-whats-actually-risky-and-what-isnt-4an5</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Six attacks are still documented on public WiFi in 2026: Man-in-the-Middle (MITM), Evil Twin (fake hotspot), packet sniffing, ARP spoofing, session hijacking, and compromised captive portals. HTTPS protects content but &lt;strong&gt;not the SNI&lt;/strong&gt; (the destination domain remains visible in plain text) — meaning the WiFi operator still sees which domains you visit. The only effective countermeasure is a VPN active &lt;strong&gt;before&lt;/strong&gt; connecting to the network. Free VPNs are explicitly counter-productive on public WiFi: they monetize your data more thoroughly than the WiFi operator would.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually happens on a public WiFi connection
&lt;/h2&gt;

&lt;p&gt;When you connect to a public WiFi network, several invisible steps happen between your device and the internet — and each one is a potential point of observation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — DHCP&lt;/strong&gt;. Your device requests an IP address from the access point, which assigns one along with the local gateway and DNS servers (typically the operator's). This means the operator decides which DNS resolver you'll use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — ARP&lt;/strong&gt;. Your device announces "I'm IP X with MAC Y". On a public network, this is broadcast to everyone — including potential attackers running tools like &lt;code&gt;arpspoof&lt;/code&gt; who can pretend to be the gateway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — DNS resolution&lt;/strong&gt;. Each website you visit triggers a DNS query. If those queries go through the WiFi operator's resolver (without DoH or VPN), the operator gets a complete log of every domain you visit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — TLS handshake&lt;/strong&gt;. For HTTPS sites, TLS 1.3 (&lt;a href="https://datatracker.ietf.org/doc/html/rfc8446" rel="noopener noreferrer"&gt;RFC 8446&lt;/a&gt;) encrypts the connection. But the &lt;strong&gt;SNI&lt;/strong&gt; (Server Name Indication) field remains in plain text during the handshake — meaning anyone watching the packets knows you visited &lt;code&gt;mybank.com&lt;/code&gt;, even if they can't see what you did there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — Encrypted traffic&lt;/strong&gt;. Application data is encrypted. But the metadata isn't: packet sizes, timing patterns, destination IPs. A determined observer can derive a lot from this.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 6 documented attacks on public WiFi in 2025-2026
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Man-in-the-Middle (MITM)
&lt;/h3&gt;

&lt;p&gt;Classic attack vector. The attacker positions themselves between you and the access point, relaying traffic while reading or modifying it. Tools like Bettercap or mitmproxy make this trivial for someone with basic networking knowledge. Mitigation: HTTPS with HSTS prevents most MITM attacks on the application layer, but DNS-level MITM still works if you don't use DoH.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evil Twin (fake access point)
&lt;/h3&gt;

&lt;p&gt;Attacker creates an AP with the same SSID as the legitimate one (e.g. &lt;code&gt;Starbucks_WiFi_Free&lt;/code&gt;), sometimes with better signal strength. Your device might auto-connect. Once connected, the attacker sees all your traffic. Mitigation: never auto-connect to open networks, verify the official SSID with staff if uncertain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Packet sniffing
&lt;/h3&gt;

&lt;p&gt;On open networks (no WPA2/WPA3), all traffic is broadcast in clear. Anyone with &lt;a href="https://www.wireshark.org/" rel="noopener noreferrer"&gt;Wireshark&lt;/a&gt; can read it. WPA2/WPA3 networks encrypt per-device, but not all "public" networks actually use encryption — many captive-portal networks remain fully open.&lt;/p&gt;

&lt;h3&gt;
  
  
  ARP spoofing
&lt;/h3&gt;

&lt;p&gt;Attacker sends crafted ARP packets to convince the network that they are the gateway. All your traffic is then routed through them. Mitigation: static ARP tables (impractical for mobile), or simply a VPN that encrypts everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Session hijacking
&lt;/h3&gt;

&lt;p&gt;Cookies set without the &lt;code&gt;Secure&lt;/code&gt; flag travel in clear. Attacker captures the session cookie and impersonates you. Modern frameworks set &lt;code&gt;Secure&lt;/code&gt; and &lt;code&gt;HttpOnly&lt;/code&gt; by default, but legacy sites still exist.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compromised captive portal
&lt;/h3&gt;

&lt;p&gt;Even legitimate captive portals can be compromised (XSS, host header injection). Attacker injects malicious JS that runs before you've connected your VPN. Mitigation: connect VPN &lt;strong&gt;first&lt;/strong&gt; when possible, dismiss the captive portal in a sandboxed browser session.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the WiFi operator sees, by setup
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your setup&lt;/th&gt;
&lt;th&gt;Domains visited&lt;/th&gt;
&lt;th&gt;Content encrypted&lt;/th&gt;
&lt;th&gt;Real IP&lt;/th&gt;
&lt;th&gt;Session cookies&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;No VPN, HTTP&lt;/td&gt;
&lt;td&gt;All&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Visible&lt;/td&gt;
&lt;td&gt;Visible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No VPN, HTTPS&lt;/td&gt;
&lt;td&gt;All (via SNI)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Visible&lt;/td&gt;
&lt;td&gt;Encrypted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTPS + DoH&lt;/td&gt;
&lt;td&gt;None (DoH encrypted)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Visible&lt;/td&gt;
&lt;td&gt;Encrypted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPN active&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Masked&lt;/td&gt;
&lt;td&gt;Encrypted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tor&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Masked&lt;/td&gt;
&lt;td&gt;Encrypted&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The verdict is uncomfortable: &lt;strong&gt;with HTTPS alone, the operator still knows every domain you visit&lt;/strong&gt;. Only DoH or VPN provides actual domain-level privacy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why HTTPS isn't enough on public WiFi
&lt;/h2&gt;

&lt;p&gt;HTTPS protects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Content of requests and responses&lt;/li&gt;
&lt;li&gt;Headers (including cookies)&lt;/li&gt;
&lt;li&gt;Form submissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HTTPS does NOT protect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;SNI&lt;/strong&gt; field (server name during TLS handshake) — visible in plain text&lt;/li&gt;
&lt;li&gt;DNS queries (unless DoH/DoT is used)&lt;/li&gt;
&lt;li&gt;The destination IP (visible by definition)&lt;/li&gt;
&lt;li&gt;Timing patterns and packet sizes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc8446" rel="noopener noreferrer"&gt;RFC 8446&lt;/a&gt; (TLS 1.3) addressed many issues but SNI plaintext remains a known leak. &lt;a href="https://datatracker.ietf.org/doc/html/rfc9116" rel="noopener noreferrer"&gt;RFC 9116&lt;/a&gt; (Encrypted Client Hello, ECH) proposes a fix but rollout is fragmented in 2026.&lt;/p&gt;




&lt;h2&gt;
  
  
  The actual role of a VPN on public WiFi
&lt;/h2&gt;

&lt;p&gt;A VPN does three concrete things on public WiFi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Encrypts end-to-end&lt;/strong&gt; between your device and the VPN server. The WiFi operator sees only encrypted traffic going to a single IP (the VPN server's).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Masks the visible IP&lt;/strong&gt;. Sites you visit see the VPN server's IP, not your real one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bypasses hostile captive portals&lt;/strong&gt;. Some captive portals inject ads or redirect to malicious pages — a VPN tunnel ignores them once active.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What a VPN doesn't do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protect against malware already installed on your device&lt;/li&gt;
&lt;li&gt;Protect against phishing pages&lt;/li&gt;
&lt;li&gt;Protect against attacks at the application layer (XSS, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For our complete VPN security audit covering 9 different test vectors, see &lt;a href="https://www.anonymflow.com/en/blog/complete-vpn-security-audit" rel="noopener noreferrer"&gt;AnonymFlow's complete VPN security audit&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Free VPN on public WiFi: a false friend
&lt;/h2&gt;

&lt;p&gt;Free VPNs make money by selling user data — that's their business model. Several documented cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hola VPN&lt;/strong&gt; (2015) sold users' bandwidth as a botnet&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hotspot Shield&lt;/strong&gt; (2017) was found to inject ads and tracking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FreeVPN&lt;/strong&gt; (2020) leaked user logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A free VPN on public WiFi often &lt;strong&gt;monetizes your data more aggressively&lt;/strong&gt; than the WiFi operator would. You traded one observer for another, possibly worse one.&lt;/p&gt;

&lt;p&gt;For the truth about free VPN trials and their hidden conditions, see &lt;a href="https://www.anonymflow.com/en/blog/vpn-free-trial-truth" rel="noopener noreferrer"&gt;The truth about VPN free trials&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Public WiFi security checklist 2026
&lt;/h2&gt;

&lt;p&gt;Before connecting:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify the SSID with venue staff (avoid Evil Twins)&lt;/li&gt;
&lt;li&gt;Turn off file sharing and AirDrop discoverability&lt;/li&gt;
&lt;li&gt;Activate your VPN &lt;strong&gt;before&lt;/strong&gt; connecting to WiFi (so the tunnel is up the moment you're online)&lt;/li&gt;
&lt;li&gt;Disable auto-connect to open networks in OS settings&lt;/li&gt;
&lt;li&gt;Have a fallback (mobile hotspot) if the WiFi is suspicious&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During connection:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Re-verify VPN is active (status indicator should show connection)&lt;/li&gt;
&lt;li&gt;Check your IP via &lt;a href="https://www.anonymflow.com/en/tools/my-ip" rel="noopener noreferrer"&gt;a public IP checker&lt;/a&gt; — should be the VPN's, not your real one&lt;/li&gt;
&lt;li&gt;Avoid sensitive operations (banking, password changes) for casual browsing only&lt;/li&gt;
&lt;li&gt;If captive portal injects unexpected JS, disconnect and use mobile data&lt;/li&gt;
&lt;li&gt;Disconnect from the WiFi when done — many devices keep credentials and auto-reconnect later&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Special cases: hotel, airport, conference, café
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hotel WiFi&lt;/strong&gt; — Often uses Cisco Meraki or similar, which can perform deep inspection and inject ads. Use VPN + your own DNS. See &lt;a href="https://www.anonymflow.com/en/blog/vpn-hotel-wifi-travel" rel="noopener noreferrer"&gt;our hotel WiFi VPN guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Airport WiFi&lt;/strong&gt; — Captive portal sometimes HTTPS-only, which blocks VPN handshake until you accept the portal. Workaround: connect via mobile hotspot to accept the portal, then switch to airport WiFi with VPN.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conference/event WiFi&lt;/strong&gt; — High Evil Twin risk during tech events (people demonstrate the attack). Always verify SSID, prefer the conference's specifically dedicated network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Café WiFi&lt;/strong&gt; — The classic packet-sniffing scenario. Open networks are still common, even in 2026. VPN mandatory.&lt;/p&gt;




&lt;h2&gt;
  
  
  Companion tools
&lt;/h2&gt;

&lt;p&gt;We maintain open-source detection tools that pair with this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ricco020/dns-leak-detector-cli" rel="noopener noreferrer"&gt;dns-leak-detector-cli&lt;/a&gt;&lt;/strong&gt; — Python CLI to verify DNS isn't leaking on your VPN&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ricco020/webrtc-leak-detector" rel="noopener noreferrer"&gt;webrtc-leak-detector&lt;/a&gt;&lt;/strong&gt; — Single HTML file to check WebRTC isn't leaking your real IP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/ricco020/vpn-speed-tester" rel="noopener noreferrer"&gt;vpn-speed-tester&lt;/a&gt;&lt;/strong&gt; — Python CLI to measure VPN overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All MIT licensed, zero-dependency, auditable.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.anonymflow.com/en/blog/public-wifi-risks-2026" rel="noopener noreferrer"&gt;AnonymFlow&lt;/a&gt; — independent VPN/privacy tooling and research. Read our full &lt;a href="https://www.anonymflow.com/en/methodology" rel="noopener noreferrer"&gt;methodology&lt;/a&gt; and the &lt;a href="https://www.anonymflow.com/en/blog/study-vpn-streaming-2026-95-test-sessions" rel="noopener noreferrer"&gt;95-session VPN streaming study&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>vpn</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>I Replaced My AI Stack With One Open-Source Agent: Testing Hermes Agent for Real Work</title>
      <dc:creator>Toheeb Temitope</dc:creator>
      <pubDate>Sun, 31 May 2026 10:47:08 +0000</pubDate>
      <link>https://dev.to/toyaab/i-replaced-my-ai-stack-with-one-open-source-agent-testing-hermes-agent-for-real-work-1pne</link>
      <guid>https://dev.to/toyaab/i-replaced-my-ai-stack-with-one-open-source-agent-testing-hermes-agent-for-real-work-1pne</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hermes-agent-2026-05-15"&gt;Hermes Agent Challenge&lt;/a&gt;: Write About Hermes Agent&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Modern AI Stack Is Getting Messy
&lt;/h2&gt;

&lt;p&gt;If you’re building anything serious with AI today, your stack probably looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ChatGPT for general reasoning&lt;/li&gt;
&lt;li&gt;Claude for long-form writing&lt;/li&gt;
&lt;li&gt;Cursor for coding&lt;/li&gt;
&lt;li&gt;Zapier for automation&lt;/li&gt;
&lt;li&gt;Browser agents for web tasks&lt;/li&gt;
&lt;li&gt;Perplexity / research tools for information gathering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Individually, each tool is powerful.&lt;/p&gt;

&lt;p&gt;Together, they feel like a distributed system glued together with copy-paste, prompts, and hope.&lt;/p&gt;

&lt;p&gt;At some point I started asking myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Could one agent replace most of this stack?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not in theory.&lt;/p&gt;

&lt;p&gt;But in real work.&lt;/p&gt;

&lt;p&gt;That question led me to test &lt;strong&gt;Hermes Agent&lt;/strong&gt; as a unified AI system.&lt;/p&gt;

&lt;p&gt;Not a chatbot.&lt;/p&gt;

&lt;p&gt;Not a plugin.&lt;/p&gt;

&lt;p&gt;A full agent runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Hermes Agent (In Practice)?
&lt;/h2&gt;

&lt;p&gt;Hermes Agent is an open-source agent framework built around one core idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI systems should persist memory, execute workflows, and coordinate sub-agents over time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of isolated conversations, it introduces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;persistent memory layer&lt;/li&gt;
&lt;li&gt;skill-based execution system&lt;/li&gt;
&lt;li&gt;multi-agent workflows&lt;/li&gt;
&lt;li&gt;tool integrations&lt;/li&gt;
&lt;li&gt;long-running task orchestration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What stood out to me wasn’t a single feature.&lt;/p&gt;

&lt;p&gt;It was the structure.&lt;/p&gt;

&lt;p&gt;It behaves less like a chatbot and more like an operating environment for AI workers.&lt;/p&gt;

&lt;p&gt;So I decided to test it like one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Experimental Setup
&lt;/h2&gt;

&lt;p&gt;I didn’t want synthetic benchmarks.&lt;/p&gt;

&lt;p&gt;I wanted real work.&lt;/p&gt;

&lt;p&gt;So I designed five practical tasks that mirror my daily engineering workflow.&lt;/p&gt;

&lt;p&gt;Each task was evaluated across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;usefulness&lt;/li&gt;
&lt;li&gt;reliability&lt;/li&gt;
&lt;li&gt;consistency&lt;/li&gt;
&lt;li&gt;autonomy&lt;/li&gt;
&lt;li&gt;developer experience&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Task 1: Research a Technical Topic
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Objective
&lt;/h3&gt;

&lt;p&gt;Research “multi-agent systems with shared memory architectures” and produce a structured summary.&lt;/p&gt;




&lt;h3&gt;
  
  
  Process
&lt;/h3&gt;

&lt;p&gt;I gave Hermes a simple instruction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Research multi-agent systems with shared memory and summarize architectural patterns.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Behind the scenes, the system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;spawned a research sub-agent&lt;/li&gt;
&lt;li&gt;gathered relevant concepts&lt;/li&gt;
&lt;li&gt;stored intermediate findings in memory&lt;/li&gt;
&lt;li&gt;consolidated results through a summarization skill&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;What stood out immediately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It did not just generate an answer&lt;/li&gt;
&lt;li&gt;It constructed a research trail&lt;/li&gt;
&lt;li&gt;It stored intermediate concepts&lt;/li&gt;
&lt;li&gt;It reused earlier findings in refinement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example memory entry (simplified):&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;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shared memory in multi-agent systems&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;key_insights&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;centralized vs distributed memory models&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;coordination bottlenecks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;state consistency challenges&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;The final output was structured like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;architecture types&lt;/li&gt;
&lt;li&gt;tradeoffs&lt;/li&gt;
&lt;li&gt;real-world examples&lt;/li&gt;
&lt;li&gt;limitations&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Strong synthesis capability&lt;/li&gt;
&lt;li&gt;Good structuring of knowledge&lt;/li&gt;
&lt;li&gt;Memory reuse improved coherence&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Weaknesses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Slight repetition in early drafts&lt;/li&gt;
&lt;li&gt;Occasional over-generalization&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Score
&lt;/h3&gt;

&lt;p&gt;Research: &lt;strong&gt;8.5/10&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 2: Write Technical Documentation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Objective
&lt;/h3&gt;

&lt;p&gt;Generate documentation for a hypothetical API service with endpoints, authentication, and examples.&lt;/p&gt;




&lt;h3&gt;
  
  
  Process
&lt;/h3&gt;

&lt;p&gt;I used a documentation skill:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Generate API documentation for a user authentication service with JWT.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hermes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;referenced previous memory patterns for API docs&lt;/li&gt;
&lt;li&gt;used structured documentation templates&lt;/li&gt;
&lt;li&gt;generated examples automatically&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Example Output Snippet
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /auth/login

Request:
{
  "email": "user@example.com",
  "password": "securepassword"
}

Response:
{
  "token": "jwt_token_here"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The output was consistent with prior documentation style (from memory)&lt;/li&gt;
&lt;li&gt;It maintained formatting across sections&lt;/li&gt;
&lt;li&gt;It reused structure patterns automatically&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Consistency across sections&lt;/li&gt;
&lt;li&gt;Good template reuse&lt;/li&gt;
&lt;li&gt;Minimal prompting required&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Weaknesses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Limited creativity in explanation style&lt;/li&gt;
&lt;li&gt;Sometimes too “templated”&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Score
&lt;/h3&gt;

&lt;p&gt;Documentation: &lt;strong&gt;8/10&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 3: Manage Project Memory
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Objective
&lt;/h3&gt;

&lt;p&gt;Simulate a project over multiple interactions and test whether Hermes retains context.&lt;/p&gt;




&lt;h3&gt;
  
  
  Process
&lt;/h3&gt;

&lt;p&gt;I created a fake project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A SaaS analytics dashboard for developer metrics.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Over multiple sessions, I added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;product decisions&lt;/li&gt;
&lt;li&gt;UI choices&lt;/li&gt;
&lt;li&gt;tech stack changes&lt;/li&gt;
&lt;li&gt;user feedback&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;This is where Hermes clearly diverged from traditional AI tools.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;decision history&lt;/li&gt;
&lt;li&gt;evolving architecture&lt;/li&gt;
&lt;li&gt;unresolved tradeoffs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example memory evolution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;v1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;React + Firebase&lt;/span&gt;
&lt;span class="na"&gt;v2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Switched to Next.js + Supabase&lt;/span&gt;
&lt;span class="na"&gt;reason&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scalability concerns&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Use Supabase as previously decided in v2 architecture.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Strong continuity across sessions&lt;/li&gt;
&lt;li&gt;Reduced need for re-explaining context&lt;/li&gt;
&lt;li&gt;Decision tracking worked surprisingly well&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Weaknesses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Memory occasionally lacked prioritization&lt;/li&gt;
&lt;li&gt;Some outdated entries persisted too long&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Score
&lt;/h3&gt;

&lt;p&gt;Memory: &lt;strong&gt;9/10&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 4: External Tool Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Objective
&lt;/h3&gt;

&lt;p&gt;Simulate integration with external APIs and tools (web search, data fetch, mock APIs).&lt;/p&gt;




&lt;h3&gt;
  
  
  Process
&lt;/h3&gt;

&lt;p&gt;I asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Fetch latest trends in AI agent frameworks and summarize.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hermes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;triggered a tool integration workflow&lt;/li&gt;
&lt;li&gt;delegated retrieval to a sub-agent&lt;/li&gt;
&lt;li&gt;consolidated results&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;Tool usage felt structured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clear separation between retrieval and reasoning&lt;/li&gt;
&lt;li&gt;results stored in memory for later reuse&lt;/li&gt;
&lt;li&gt;tool outputs treated as first-class data&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Example Workflow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent → Tool Request → External API
      → Sub-Agent Processing
      → Memory Storage
      → Final Synthesis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Clean tool abstraction&lt;/li&gt;
&lt;li&gt;Reusable tool outputs&lt;/li&gt;
&lt;li&gt;Good workflow orchestration&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Weaknesses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Integration setup still requires engineering effort&lt;/li&gt;
&lt;li&gt;Not plug-and-play like Zapier&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Score
&lt;/h3&gt;

&lt;p&gt;Automation: &lt;strong&gt;8/10&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Task 5: Multi-Step Planning
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Objective
&lt;/h3&gt;

&lt;p&gt;Plan a full MVP for a developer productivity tool.&lt;/p&gt;




&lt;h3&gt;
  
  
  Process
&lt;/h3&gt;

&lt;p&gt;I gave a broad prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Plan an MVP for a developer analytics tool with onboarding, metrics, and dashboards.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hermes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;created a planning sub-agent&lt;/li&gt;
&lt;li&gt;broke task into phases&lt;/li&gt;
&lt;li&gt;stored milestones in memory&lt;/li&gt;
&lt;li&gt;refined plan iteratively&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Example Plan Structure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Phase 1: Data ingestion&lt;/li&gt;
&lt;li&gt;Phase 2: Metrics engine&lt;/li&gt;
&lt;li&gt;Phase 3: Dashboard UI&lt;/li&gt;
&lt;li&gt;Phase 4: API integrations&lt;/li&gt;
&lt;li&gt;Phase 5: Deployment&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;The most impressive part was iteration.&lt;/p&gt;

&lt;p&gt;Each refinement built on previous planning state.&lt;/p&gt;




&lt;h3&gt;
  
  
  Strengths
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Strong decomposition skills&lt;/li&gt;
&lt;li&gt;Persistent planning state&lt;/li&gt;
&lt;li&gt;Clear execution roadmap&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Weaknesses
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sometimes over-engineered plans&lt;/li&gt;
&lt;li&gt;Needed constraint tuning&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Score
&lt;/h3&gt;

&lt;p&gt;Planning: &lt;strong&gt;8.5/10&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Overall Scorecard
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Research&lt;/td&gt;
&lt;td&gt;8.5/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Planning&lt;/td&gt;
&lt;td&gt;8.5/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;9/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automation&lt;/td&gt;
&lt;td&gt;8/10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer Experience&lt;/td&gt;
&lt;td&gt;7.5/10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Where Hermes Agent Becomes Clearly Better
&lt;/h2&gt;

&lt;p&gt;Compared to traditional AI tools:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Continuity
&lt;/h3&gt;

&lt;p&gt;Most AI tools reset after every session.&lt;/p&gt;

&lt;p&gt;Hermes does not.&lt;/p&gt;

&lt;p&gt;This alone changes workflows significantly.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Memory-Driven Decisions
&lt;/h3&gt;

&lt;p&gt;Instead of re-explaining context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;decisions persist&lt;/li&gt;
&lt;li&gt;architecture evolves&lt;/li&gt;
&lt;li&gt;preferences accumulate&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Workflow Composition
&lt;/h3&gt;

&lt;p&gt;Instead of single prompts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multi-step execution chains&lt;/li&gt;
&lt;li&gt;reusable skills&lt;/li&gt;
&lt;li&gt;persistent state&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Multi-Agent Execution
&lt;/h3&gt;

&lt;p&gt;Tasks are no longer linear.&lt;/p&gt;

&lt;p&gt;They become parallelized across sub-agents.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Dedicated Tools Still Win
&lt;/h2&gt;

&lt;p&gt;To be clear, Hermes is not a replacement for everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cursor still wins in IDE experience
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;real-time code navigation&lt;/li&gt;
&lt;li&gt;deep repository awareness&lt;/li&gt;
&lt;li&gt;UI integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Zapier still wins in plug-and-play automation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;zero setup workflows&lt;/li&gt;
&lt;li&gt;hundreds of integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. ChatGPT / Claude still win in simplicity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;instant responses&lt;/li&gt;
&lt;li&gt;no system setup&lt;/li&gt;
&lt;li&gt;lower cognitive overhead&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Tradeoff Is Clear
&lt;/h2&gt;

&lt;p&gt;Hermes is powerful.&lt;/p&gt;

&lt;p&gt;But it is also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;more complex&lt;/li&gt;
&lt;li&gt;more architectural&lt;/li&gt;
&lt;li&gt;more system-oriented&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It behaves less like a tool and more like a platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  Would I Use Hermes Agent Every Day?
&lt;/h2&gt;

&lt;p&gt;Yes — but not as a replacement for everything.&lt;/p&gt;

&lt;p&gt;I would use it as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a long-running project brain&lt;/li&gt;
&lt;li&gt;a research companion&lt;/li&gt;
&lt;li&gt;a planning system&lt;/li&gt;
&lt;li&gt;a memory layer for engineering work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a quick Q&amp;amp;A chatbot&lt;/li&gt;
&lt;li&gt;a lightweight writing assistant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It shines when:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;context matters over time.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Who Should Use Hermes Agent Right Now?
&lt;/h2&gt;

&lt;p&gt;Hermes Agent is most useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI engineers building multi-step systems&lt;/li&gt;
&lt;li&gt;startup teams managing evolving context&lt;/li&gt;
&lt;li&gt;researchers tracking long-term work&lt;/li&gt;
&lt;li&gt;developers building agentic workflows&lt;/li&gt;
&lt;li&gt;anyone tired of re-explaining context to AI tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;casual chat use&lt;/li&gt;
&lt;li&gt;single-turn queries&lt;/li&gt;
&lt;li&gt;lightweight automation&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Testing Hermes Agent felt less like testing a chatbot…&lt;/p&gt;

&lt;p&gt;and more like testing an early version of an AI operating layer.&lt;/p&gt;

&lt;p&gt;Not perfect.&lt;/p&gt;

&lt;p&gt;Not simple.&lt;/p&gt;

&lt;p&gt;But structurally different.&lt;/p&gt;

&lt;p&gt;And that difference matters.&lt;/p&gt;

&lt;p&gt;Because the real question is no longer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How smart is the model?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But instead:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How much does the system remember, coordinate, and evolve over time?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And on that axis, Hermes Agent points in a direction most AI tools are not even trying to go yet.&lt;/p&gt;

</description>
      <category>hermesagentchallenge</category>
      <category>devchallenge</category>
      <category>agents</category>
    </item>
    <item>
      <title>I let the AI write the report, not decide the alerts</title>
      <dc:creator>TiltedLunar123</dc:creator>
      <pubDate>Sun, 31 May 2026 10:45:18 +0000</pubDate>
      <link>https://dev.to/tiltedlunar123/i-let-the-ai-write-the-report-not-decide-the-alerts-593o</link>
      <guid>https://dev.to/tiltedlunar123/i-let-the-ai-write-the-report-not-decide-the-alerts-593o</guid>
      <description>&lt;p&gt;I've been building a SOC triage tool called TriageLens, and the whole thing started from one annoyance. Every "AI security analyst" demo I tried was just a chatbot with a log pasted into the prompt. Ask it twice, get two different verdicts. For triage that's useless. If the tool says "brute force, critical" one run and "looks fine" the next, I can't trust either answer.&lt;/p&gt;

&lt;p&gt;So I drew a hard line early. The AI doesn't get to decide what's a finding. It only gets to write the finding up.&lt;/p&gt;

&lt;h2&gt;
  
  
  the split
&lt;/h2&gt;

&lt;p&gt;Parsing, detection, and risk scoring are plain TypeScript. No model involved. The pipeline normalizes Windows Security 4688, Sysmon Event 1, Linux SSH &lt;code&gt;auth.log&lt;/code&gt;, and generic JSON into one event shape, runs a list of detection rules over those events, and scores the result 0-100. All deterministic. Same logs in, same findings out, every time.&lt;/p&gt;

&lt;p&gt;The AI layer sits at the very end. It takes the structured findings that already exist and turns them into analyst-style prose: a summary, per-finding notes, prioritized next steps. If I swap the provider from the built-in demo one to Ollama to Claude, the findings and the MITRE mapping don't move at all. Only the wording changes.&lt;/p&gt;

&lt;p&gt;That property is the part I actually care about. The detections are auditable. The model is just the writer.&lt;/p&gt;

&lt;h2&gt;
  
  
  a rule is just a function
&lt;/h2&gt;

&lt;p&gt;Each detection rule is a pure function that looks at the events and returns evidence strings. Empty array means it didn't fire. Here's the one I'm happiest with, the chained one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;successful-auth-after-brute-force&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Successful login after brute-force activity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;critical&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;techniques&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;techniques&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;T1110&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;T1078&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;detect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;failsByIp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;countFailuresByIp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;evidence&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="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="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;events&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth-success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceIp&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;failsByIp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceIp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;evidence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s2"&gt;`Successful login for "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" from &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceIp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; after &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;failsByIp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceIp&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt; failures`&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;evidence&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;On its own, a pile of failed SSH logons is just noise. Lots of hosts get sprayed all day. What changes the picture is a success from the same IP that just failed a bunch. The brute-force rule alone is &lt;code&gt;high&lt;/code&gt;. The success-after-brute-force rule is &lt;code&gt;critical&lt;/code&gt;, mapped to T1110 and T1078, because at that point you're probably looking at a real compromise, not background scanning.&lt;/p&gt;

&lt;p&gt;Writing it as a plain function means I can unit test it with a handful of fake events and know it fires on exactly the case I want. No prompt tuning, no "please respond in JSON." &lt;code&gt;countFailuresByIp&lt;/code&gt; is about six lines and counts &lt;code&gt;auth-failure&lt;/code&gt; events per source IP. The whole rule file reads top to bottom like a checklist.&lt;/p&gt;

&lt;h2&gt;
  
  
  what I tried first and dropped
&lt;/h2&gt;

&lt;p&gt;My first version actually did hand the raw logs to the model and ask it to return findings as JSON. It worked in the demo and fell apart the moment I fed it anything weird. Sometimes it invented an event ID that wasn't in the log. Once it confidently flagged a normal &lt;code&gt;svchost&lt;/code&gt; as a LOLBin. And the JSON would occasionally come back with a trailing comment or markdown fence that broke the parser.&lt;/p&gt;

&lt;p&gt;I spent a day trying to prompt my way out of that and then gave up on the approach entirely. Moving detection into code wasn't a performance decision, it was a "I need to be able to trust this" decision. The model is great at writing the summary. It's bad at being the source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  what's still rough
&lt;/h2&gt;

&lt;p&gt;The honest part. It only reads EVTX if you've already exported it to JSON. There's no native &lt;code&gt;.evtx&lt;/code&gt; binary parser yet, which is the next thing on the roadmap, and right now that export step is an annoying manual hop. The rule set is small, seven rules, so it catches the obvious stuff (encoded PowerShell, Office spawning a child process, log clearing, the SSH chain) and misses plenty. I want Sigma import so I'm not the only one writing detections in my own format.&lt;/p&gt;

&lt;p&gt;It also isn't a SIEM and I'm not pretending it is. It's a learning project and a triage aid. It does not replace tuned detection content or a human deciding what matters.&lt;/p&gt;

&lt;p&gt;It runs with zero setup though. &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;npm run dev&lt;/code&gt;, a sample log is already loaded, click Analyze. The default provider needs no API key, so you can see the whole loop without signing up for anything.&lt;/p&gt;

&lt;p&gt;Repo's here if you want to poke at it or tell me which rule is wrong: &lt;a href="https://github.com/TiltedLunar123/triagelens" rel="noopener noreferrer"&gt;https://github.com/TiltedLunar123/triagelens&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built with React, TypeScript, Vite, and vitest for the rule tests. Happy to take detection ideas, that's the part I most want to grow.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>typescript</category>
      <category>react</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
