<?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: rocketsquirreldev</title>
    <description>The latest articles on DEV Community by rocketsquirreldev (@rocketsquirreldev).</description>
    <link>https://dev.to/rocketsquirreldev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3849271%2F5c7a54bb-000b-44cb-ac7c-e19347a618a9.jpg</url>
      <title>DEV Community: rocketsquirreldev</title>
      <link>https://dev.to/rocketsquirreldev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rocketsquirreldev"/>
    <language>en</language>
    <item>
      <title>[x509Lab] Breaking Down a 4,500-Line Single File App: The Bugs I Found (x509Lab v1.7.1)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Wed, 03 Jun 2026 13:18:29 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/x509lab-breaking-down-a-4500-line-single-file-app-the-bugs-i-found-x509lab-v171-4dk9</link>
      <guid>https://dev.to/rocketsquirreldev/x509lab-breaking-down-a-4500-line-single-file-app-the-bugs-i-found-x509lab-v171-4dk9</guid>
      <description>&lt;p&gt;Hey everyone, RocketSquirrel here. I am a solo developer building &lt;strong&gt;x509Lab&lt;/strong&gt;, a browser-based visual tool for managing and testing X.509 certificate chains. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2hcjv4gqoi08ktiityj.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%2Fz2hcjv4gqoi08ktiityj.png" alt=" " width="469" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lately, I realized my &lt;code&gt;index.html&lt;/code&gt; file had bloated into a massive &lt;strong&gt;4,558-line monster&lt;/strong&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1,248 lines of CSS inside &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;2,712 lines of JavaScript inside &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;598 lines of HTML structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"As long as it runs fine," I kept telling myself. But finding a single utility function was becoming an endurance test. This weekend, I decided to refactor and split it up. Splitting the files took 5 minutes. But then, the real engineering work began because two hidden bugs crawled out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug 1: The Illusion of Global &lt;code&gt;event.target&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;I had a simple tab-switching function that worked flawlessly when clicking the UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;switchTab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.tab-btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- The culprit&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;tab&lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;verify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;verifyChain&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In an inline HTML handler like &lt;code&gt;&amp;lt;button onclick="switchTab('builder')"&amp;gt;&lt;/code&gt;, the browser implicitly passes the &lt;code&gt;event&lt;/code&gt; object. It always worked during manual clicking.&lt;/p&gt;

&lt;p&gt;However, during refactoring, I triggered &lt;code&gt;switchTab()&lt;/code&gt; programmatically in a script test. Boom: &lt;code&gt;TypeError: Cannot read properties of undefined (reading 'target')&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Because it was a single file, my manual test suite never hit this programmatic trigger. I had to refactor the function to search for the element explicitly using &lt;code&gt;querySelector&lt;/code&gt; rather than relying on the implicit global event context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug 2: Vercel's Catch-All Route Ate My Assets
&lt;/h3&gt;

&lt;p&gt;Everything ran beautifully on my local server. I deployed to Vercel, opened the live link, and was greeted with a naked, unstyled HTML page. No CSS. No JS.&lt;/p&gt;

&lt;p&gt;The issue was inside my &lt;code&gt;vercel.json&lt;/code&gt; routing configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/(.*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"dest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/index.html"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This catch-all route redirects every single path to &lt;code&gt;index.html&lt;/code&gt;. When x509Lab was a single-file application, this was fine because there were no external static assets to fetch. &lt;/p&gt;

&lt;p&gt;But once I broke it down, requests for &lt;code&gt;/styles.css&lt;/code&gt; and &lt;code&gt;/app.js&lt;/code&gt; were being intercepted by Vercel and serving the &lt;code&gt;index.html&lt;/code&gt; payload instead. I patched it by adding explicit static file matching rules ahead of the catch-all redirect block.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;\"It just works\" hides bugs:&lt;/strong&gt; The &lt;code&gt;event.target&lt;/code&gt; bug was always there, sleeping silently because my manual test coverage was narrow. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local environment lies:&lt;/strong&gt; A local file server will happily serve separate static files out of the box, but production deployment platforms (like Vercel) have complex routing engines that behave differently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring is testing:&lt;/strong&gt; Moving text blocks from one file to another is easy. The real cost of refactoring is the rigorous regression testing required afterward to ensure nothing broke.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that the codebase is clean, my next task is writing formal unit tests for my custom ASN.1/DER parser. No more coding on prayer!&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Check out the clean v1.7.1 build:&lt;/strong&gt; &lt;a href="https://x509lab.vercel.app" rel="noopener noreferrer"&gt;https://x509lab.vercel.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>[DeskFlow]Mapping Thunderbolt 5: Adding 23 New Devices to DeskFlow's Library</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Tue, 02 Jun 2026 13:21:08 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/deskflowmapping-thunderbolt-5-adding-23-new-devices-to-deskflows-library-562b</link>
      <guid>https://dev.to/rocketsquirreldev/deskflowmapping-thunderbolt-5-adding-23-new-devices-to-deskflows-library-562b</guid>
      <description>&lt;p&gt;Hey everyone, RocketSquirrel here! I’m an embedded developer by day and an indie hacker by night, currently building &lt;strong&gt;DeskFlow&lt;/strong&gt;—a visual canvas for planning desk setups and cable routing.&lt;/p&gt;

&lt;p&gt;As a developer using an M3 Max MacBook Pro, I know how painful it is to buy a brand new USB-C hub or monitor, only to realize the port bandwidth doesn't match your laptop's output capabilities. Cable planning requires exact specs.&lt;/p&gt;

&lt;p&gt;That’s why I just rolled out a massive library update, adding 23 new devices with meticulously researched port metadata.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Complete MacBook Lineup
&lt;/h3&gt;

&lt;p&gt;You can now drag and drop the entire modern Apple laptop lineup into your canvas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;MacBook Air:&lt;/strong&gt; M1 (2020) through the brand new M4 (2025) 13" &amp;amp; 15" models.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;MacBook Pro:&lt;/strong&gt; M2 13" up to the heavy-hitting M4 Pro/Max 14" &amp;amp; 16" models.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why port data matters:&lt;/strong&gt; Every MacBook has a different physical port layout. Some have MagSafe, some only have two Type-C ports, and the new M4 Pros feature &lt;strong&gt;Thunderbolt 5&lt;/strong&gt;. By hardcoding the exact Apple Tech Specs into the nodes, DeskFlow physically prevents you from planning a setup with incompatible cables or insufficient ports.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitors &amp;amp; Hubs
&lt;/h3&gt;

&lt;p&gt;I also added displays that are heavily requested by designers and developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Kuycon P27D 4K 27":&lt;/strong&gt; Includes dual HDMI 2.1, DP 1.4, and USB-C 100W PD.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;BenQ PD2725U 27" 4K:&lt;/strong&gt; Perfect for testing Thunderbolt 3 daisy-chain layouts.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;LG 32UN880-B 32" Ergo:&lt;/strong&gt; A staple for clean, C-clamp layouts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Streaming &amp;amp; Creator Gear
&lt;/h3&gt;

&lt;p&gt;If you stream or record podcasts at your desk, you can now route audio and video capture cables accurately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Focusrite Scarlett 2i2 4th Gen&lt;/strong&gt; (Audio Interface)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;HyperX QuadCast S&lt;/strong&gt; (USB Mic)&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Elgato HD60 X&lt;/strong&gt; (Capture Card with HDMI passthrough)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Input &amp;amp; Others
&lt;/h3&gt;

&lt;p&gt;Finally, rounding out the wireless desk aesthetics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Apple Magic Keyboard &amp;amp; Trackpad (The new USB-C versions)&lt;/li&gt;
&lt;li&gt;  Logitech MX Keys S &amp;amp; Keychron Q1 Pro&lt;/li&gt;
&lt;li&gt;  Mac Mini M2, iPad Air 11" M2, and NVIDIA Shield TV Pro.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can search for any of these models directly in the left sidebar and start wiring up your dream setup.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Try it out directly in your browser:&lt;/strong&gt; &lt;a href="https://deskflow-gold.vercel.app" rel="noopener noreferrer"&gt;https://deskflow-gold.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there is a specific piece of gear you use daily that isn't in the library yet, drop the model name in the comments and I'll add it to the next batch!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>hardware</category>
      <category>desksetup</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>Stop Building X.509 Chains Manually: 1-Click Presets for TLS &amp; Code Signing (x509Lab v1.7.0)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Mon, 01 Jun 2026 13:26:32 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/stop-building-x509-chains-manually-1-click-presets-for-tls-code-signing-x509lab-v170-4a6d</link>
      <guid>https://dev.to/rocketsquirreldev/stop-building-x509-chains-manually-1-click-presets-for-tls-code-signing-x509lab-v170-4a6d</guid>
      <description>&lt;p&gt;Hey everyone, RocketSquirrel here! 🐿️ By day, I'm an embedded software developer, and by night, I build side projects. &lt;/p&gt;

&lt;p&gt;I'm the creator of &lt;strong&gt;x509Lab&lt;/strong&gt;, a purely client-side browser tool for visualizing and generating X.509 certificate chains. Today, I'm pushing the v1.7.0 update, and it solves the most annoying part of testing PKI infrastructure: &lt;strong&gt;node-by-node manual setup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpa8dgu2yezyn1h5h4ula.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%2Fpa8dgu2yezyn1h5h4ula.png" alt=" " width="484" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem: Remembering RFC 5280
&lt;/h3&gt;

&lt;p&gt;If you wanted to build a simple TLS server chain in the previous version, you had to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a Root CA node.&lt;/li&gt;
&lt;li&gt;Add an Intermediate CA node.&lt;/li&gt;
&lt;li&gt;Add a Leaf node.&lt;/li&gt;
&lt;li&gt;Manually link them all together.&lt;/li&gt;
&lt;li&gt;Figure out which Key Usage and Extended Key Usage (EKU) extensions to apply (&lt;code&gt;keyEncipherment&lt;/code&gt;? &lt;code&gt;serverAuth&lt;/code&gt;?).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It was tedious. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: 1-Click Chain Presets
&lt;/h3&gt;

&lt;p&gt;I've completely automated this process. You can now click the &lt;strong&gt;📦 Chain Presets&lt;/strong&gt; button in the sidebar and choose from three ready-to-use architectures.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Preset&lt;/th&gt;
&lt;th&gt;Chain Structure&lt;/th&gt;
&lt;th&gt;Key Usage&lt;/th&gt;
&lt;th&gt;EKU&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;🌐 TLS Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Root → Intermediate → Server&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;digitalSignature&lt;/code&gt;, &lt;code&gt;keyEncipherment&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;serverAuth&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;📦 Code Signing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Root → Signing CA → Code Cert&lt;/td&gt;
&lt;td&gt;&lt;code&gt;digitalSignature&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;codeSigning&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;✉️ S/MIME&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Root → Email Cert&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;digitalSignature&lt;/code&gt;, &lt;code&gt;keyEncipherment&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;emailProtection&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2F96xz3kl77ona55q1m7zx.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%2F96xz3kl77ona55q1m7zx.png" alt=" " width="512" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app also automatically selects the modern recommended algorithms for you (e.g., &lt;code&gt;ECDSA P-256&lt;/code&gt; for TLS, and &lt;code&gt;RSA-2048&lt;/code&gt; for Code Signing). &lt;/p&gt;

&lt;h3&gt;
  
  
  How it works under the hood (Web Crypto API)
&lt;/h3&gt;

&lt;p&gt;To make this work, I had to rewrite my internal &lt;code&gt;buildTBSCertificate()&lt;/code&gt; function. &lt;/p&gt;

&lt;p&gt;Previously, it only handled the &lt;code&gt;BasicConstraints&lt;/code&gt; extension (to flag CA:TRUE). Now, it accepts &lt;code&gt;keyUsageBits&lt;/code&gt; and &lt;code&gt;ekuOids&lt;/code&gt; arrays, dynamically applying strict DER encoding to inject the correct extensions into the generated certificates based on the selected preset. &lt;/p&gt;

&lt;p&gt;And as always, &lt;strong&gt;zero data leaves your browser.&lt;/strong&gt; Everything is computed locally using the Web Crypto API. No backend, no OpenSSL installation required.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Try it live in your browser:&lt;/strong&gt; &lt;a href="https://x509lab.vercel.app" rel="noopener noreferrer"&gt;https://x509lab.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are a DevOps engineer or just studying PKI, I hope this saves you some headache! Let me know what you think.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>cryptography</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>Curing 'Blank Canvas Paralysis' with 1-Click Templates (DeskFlow Update)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Wed, 20 May 2026 12:49:11 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/curing-blank-canvas-paralysis-with-1-click-templates-deskflow-update-3pbc</link>
      <guid>https://dev.to/rocketsquirreldev/curing-blank-canvas-paralysis-with-1-click-templates-deskflow-update-3pbc</guid>
      <description>&lt;p&gt;I'm building &lt;strong&gt;DeskFlow&lt;/strong&gt;, a visual canvas tool for planning desk setups and routing cables. &lt;/p&gt;

&lt;p&gt;Recently, I noticed a huge UX friction point: &lt;strong&gt;Blank Canvas Paralysis&lt;/strong&gt;. When users first open the app and stare at a massive, empty dark grid, it’s intimidating. Dragging out nodes one by one, connecting the ports, and organizing the layout from scratch requires too much upfront cognitive load. &lt;/p&gt;

&lt;p&gt;To fix this, I just shipped a &lt;strong&gt;Setup Templates&lt;/strong&gt; feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: Starter Kits
&lt;/h3&gt;

&lt;p&gt;Instead of forcing users to start from zero, I built a feature that instantly loads fully wired, highly realistic desk configurations with a single click. &lt;/p&gt;

&lt;p&gt;Users can access this via the grid icon in the top right. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fty7vihut28e45zrep7sr.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%2Fty7vihut28e45zrep7sr.png" alt=" " width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I launched with 3 core templates:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnffpa5kni7vz2cpgaiyu.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%2Fnffpa5kni7vz2cpgaiyu.png" alt=" " width="521" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Home Office&lt;/strong&gt;&lt;br&gt;
The classic clean setup. A MacBook Air connected to a Thunderbolt Hub, routing out to a 4K monitor, mechanical keyboard, and an MX Master mouse. It shows users exactly how a single-cable hub setup should look.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Gaming Station&lt;/strong&gt;&lt;br&gt;
For the console hoarders. This template wires a PS5, Xbox Series X, Steam Deck, and Nintendo Switch into a single OLED TV, perfectly managing the HDMI port distribution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Creator Studio&lt;/strong&gt;&lt;br&gt;
A heavy-duty layout featuring a Mac Studio, 4K monitors, Cam Link, a Blue Yeti mic, and a Stream Deck. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why this works
&lt;/h3&gt;

&lt;p&gt;It turns a daunting creation task into a simple editing task. Users load a template that closely resembles their goal, and then simply tweak it—swapping out a mouse, deleting a monitor, or adding a docking station. &lt;/p&gt;

&lt;p&gt;As a bonus, loading a template instantly auto-populates the Shopping List panel with all the necessary cables and estimated costs.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Try loading a template here:&lt;/strong&gt; &lt;a href="https://deskflow-gold.vercel.app" rel="noopener noreferrer"&gt;https://deskflow-gold.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are building a canvas or whiteboard-based app, I highly recommend adding pre-built templates early on. It dramatically improves the "Aha!" moment for new users.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ux</category>
      <category>frontend</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>No more vague 'Signature FAIL': x509Lab now tells you exactly WHY your cert chain is broken 🔍</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Wed, 13 May 2026 13:11:24 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/no-more-vague-signature-fail-x509lab-now-tells-you-exactly-why-your-cert-chain-is-broken-1hja</link>
      <guid>https://dev.to/rocketsquirreldev/no-more-vague-signature-fail-x509lab-now-tells-you-exactly-why-your-cert-chain-is-broken-1hja</guid>
      <description>&lt;p&gt;Hey everyone, RocketSquirrel here. I am building &lt;strong&gt;x509Lab&lt;/strong&gt;, a browser-based GUI tool for visualizing and testing X.509 certificate chains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5ygkekcu44bmn2nk1zo.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%2Fd5ygkekcu44bmn2nk1zo.png" alt=" " width="495" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the previous versions, clicking the 'Verify Chain' button was a bit frustrating. If your chain was broken, it would just throw a generic &lt;code&gt;❌ Signature FAIL&lt;/code&gt; message. It didn't tell you &lt;em&gt;which&lt;/em&gt; certificate failed, or &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I spent this weekend fixing that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Granular Verification &amp;amp; Actionable Hints
&lt;/h3&gt;

&lt;p&gt;The verification engine now breaks down the chain check into 8 distinct cryptographic and structural validations (Validity, CA Flags, DN Matching, Signatures, Path Length, Key Usage, etc.).&lt;/p&gt;

&lt;p&gt;If a check fails, the UI now points to the exact certificate and gives you a hint on how to fix it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario: Expired Certificate&lt;/strong&gt;
&lt;code&gt;❌ [Intermediate CA] Validity Period FAIL&lt;/code&gt;
&lt;code&gt;💡 This certificate expired 365 days ago. Issue a new one.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&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%2F689jbe3kh2r61jolg2g1.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%2F689jbe3kh2r61jolg2g1.png" alt=" " width="289" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario: Broken Chain (DN Mismatch)&lt;/strong&gt;
&lt;code&gt;❌ [Leaf Cert] DN Mismatch&lt;/code&gt;
&lt;code&gt;💡 Issuer: "Wrong Root CA" -&amp;gt; Subject: "Demo Root CA" Check your signing CA.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&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%2Fxin4e6bs1clzz450ctpk.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%2Fxin4e6bs1clzz450ctpk.png" alt=" " width="309" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Copy for Jira/Slack
&lt;/h3&gt;

&lt;p&gt;I also added a &lt;strong&gt;Copy Report&lt;/strong&gt; button. With one click, you get a clean text readout of the entire validation result, which is perfect for pasting into Slack to prove to the backend team that their Intermediate CA is indeed expired.&lt;/p&gt;

&lt;p&gt;Like everything in x509Lab, this runs 100% locally via the Web Crypto API. Your keys and certs never touch a server.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Try it live here:&lt;/strong&gt; &lt;a href="https://x509lab.vercel.app" rel="noopener noreferrer"&gt;https://x509lab.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know if this saves you from staring at OpenSSL man pages!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>devops</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>[CryptoTradingBot] Analyzing 70 Live Trades of My Python Crypto Bot (v8.04 Post-Mortem)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Mon, 11 May 2026 13:22:13 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/analyzing-70-live-trades-of-my-python-crypto-bot-v804-post-mortem-5acl</link>
      <guid>https://dev.to/rocketsquirreldev/analyzing-70-live-trades-of-my-python-crypto-bot-v804-post-mortem-5acl</guid>
      <description>&lt;p&gt;I’ve been running version 8.04 of my Python-based crypto trading bot live for about a month. Instead of just looking at the final PnL, I built a dashboard to analyze the exact entry/exit logs of all 70 trades. &lt;/p&gt;

&lt;p&gt;Here is what the raw data taught me about the gap between theoretical algorithms and live markets.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Stats: A Tale of Two Months
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total Trades:&lt;/strong&gt; 70&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Win Rate:&lt;/strong&gt; 48.6% &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;April (35 trades):&lt;/strong&gt; 43% win rate, net negative.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;May (35 trades):&lt;/strong&gt; 54% win rate, net positive.&lt;/li&gt;
&lt;/ul&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%2F9oy2w43q1f55nlidx179.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%2F9oy2w43q1f55nlidx179.png" alt=" " width="800" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The bot clearly improved in May. In April, my logging showed two fatal flaws: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Sideways Trap:&lt;/strong&gt; The bot entered BTC 4 times in a single day during a chop zone, getting stopped out repeatedly. My 1-hour cooldown logic was simply too short.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simultaneous Liquidations:&lt;/strong&gt; The bot held LONG positions in LINK and ETH simultaneously. When the market dipped, both hit their stop-losses at the exact same minute, doubling my daily drawdown.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Risk/Reward Illusion
&lt;/h3&gt;

&lt;p&gt;This was the most humbling discovery. My algorithm is strictly coded to aim for a &lt;strong&gt;3:1 Risk/Reward ratio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, the real-world data showed an average win of 0.80 and an average loss of 0.70. My actual R/R ratio was &lt;strong&gt;1.14:1&lt;/strong&gt;. Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trailing Stops:&lt;/strong&gt; My &lt;code&gt;EXIT_PROFIT_SECURE&lt;/code&gt; trailing stop logic was too aggressive. It protected my capital by closing trades early during minor pullbacks, but it effectively prevented the bot from ever reaching the 3:1 target. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Asset Breakdown
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;$LINK (9W 9L):&lt;/strong&gt; My most profitable pair. The "Volume Climax Filter" I added in v8.03 worked perfectly here, preventing FOMO entries at the top of pumps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$ETH (7W 9L):&lt;/strong&gt; The absolute worst performer. The stop-losses were large, and the take-profits were tiny.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Next Steps for v8.05
&lt;/h3&gt;

&lt;p&gt;Data analysis gives you a clear roadmap. My next commits will include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stricter ETH Entry:&lt;/strong&gt; Bumping the ADX threshold limit to 25 specifically for ETH.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased Cooldowns:&lt;/strong&gt; Changing the post-loss cooldown for BTC from 1 hour to 2 hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Circuit Breaker:&lt;/strong&gt; If the total daily loss exceeds a specific threshold, halt all new entries for 24 hours to prevent cascading simultaneous stops.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Algo-trading is 10% writing trading logic and 90% debugging your own assumptions through data. Back to the code!&lt;/p&gt;

</description>
      <category>python</category>
      <category>algotrading</category>
      <category>data</category>
      <category>lessons</category>
    </item>
    <item>
      <title>Visualizing Certificate Expiry in the Browser (x509Lab v1.5.0)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Fri, 08 May 2026 12:38:29 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/visualizing-certificate-expiry-in-the-browser-x509lab-v150-445m</link>
      <guid>https://dev.to/rocketsquirreldev/visualizing-certificate-expiry-in-the-browser-x509lab-v150-445m</guid>
      <description>&lt;p&gt;Hey everyone, I'm RocketSquirrel. I build &lt;strong&gt;x509Lab&lt;/strong&gt;, a purely client-side web tool for visualizing and generating X.509 certificate chains. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0dwfxxvfyvwjh8ol3o18.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%2F0dwfxxvfyvwjh8ol3o18.png" alt=" " width="485" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you work in DevOps, Backend, or IT Infra, you know the quiet terror of a production certificate expiring because someone forgot to track it. &lt;/p&gt;

&lt;p&gt;When visualizing complex PKI trees (Root -&amp;gt; Multiple Intermediates -&amp;gt; Dozens of Leafs) in x509Lab, clicking into every single node to check its expiry date was becoming a chore. So for the v1.5.0 update, I built a visual warning system directly into the canvas nodes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Expiry Badges
&lt;/h3&gt;

&lt;p&gt;Now, the moment you upload or generate a certificate, the node card displays a color-coded badge based on its remaining lifespan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;VALID (&amp;gt; 90 days):&lt;/strong&gt; All good.&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;D-XX (31~90 days):&lt;/strong&gt; Warning zone.&lt;/li&gt;
&lt;li&gt;🟠 &lt;strong&gt;D-XX (&amp;lt; 30 days):&lt;/strong&gt; Danger zone. A small orange dot also appears on the node header.&lt;/li&gt;
&lt;li&gt;🔴 &lt;strong&gt;D-XX (&amp;lt;= 7 days) or EXPIRED:&lt;/strong&gt; Critical. A bright red dot appears on the header.&lt;/li&gt;
&lt;/ul&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%2Fas5zccevwyvpdulbhafs.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%2Fas5zccevwyvpdulbhafs.png" alt=" " width="800" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This makes it incredibly easy to zoom out on your 5000x5000 canvas and instantly spot which certificates in your chain need to be replaced. &lt;/p&gt;

&lt;h3&gt;
  
  
  Bug Fix: Save/Load State Loss
&lt;/h3&gt;

&lt;p&gt;I also fixed a frustrating state management bug. Previously, if you generated certificates inside the app, saved your workspace to a &lt;code&gt;.json&lt;/code&gt; file, and loaded it later, the certificates would disappear (only the empty nodes remained). The serialization logic was missing the dynamically generated PEM strings. This is now fully patched—you can safely save your test PKI environments and restore them anytime.&lt;/p&gt;

&lt;p&gt;As always, everything runs locally via the Web Crypto API. No backend, no data collection. &lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Try it here:&lt;/strong&gt; &lt;a href="https://x509lab.vercel.app" rel="noopener noreferrer"&gt;https://x509lab.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Instagram Link:&lt;/strong&gt; &lt;a href="https://www.instagram.com/reel/DYE_C6KqL3Z/?utm_source=ig_web_copy_link&amp;amp;igsh=MzRlODBiNWFlZA==" rel="noopener noreferrer"&gt;https://www.instagram.com/reel/DYE_C6KqL3Z/?utm_source=ig_web_copy_link&amp;amp;igsh=MzRlODBiNWFlZA==&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next up on the roadmap: One-click templates for TLS Server, Code Signing, and S/MIME chains!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>openssl</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>[DeskFlow]Added 11 New Devices to DeskFlow (Including Windows Laptops &amp; UPS!)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Sun, 03 May 2026 12:27:39 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/deskflowadded-11-new-devices-to-deskflow-including-windows-laptops-ups-10ge</link>
      <guid>https://dev.to/rocketsquirreldev/deskflowadded-11-new-devices-to-deskflow-including-windows-laptops-ups-10ge</guid>
      <description>&lt;p&gt;Hey everyone, RocketSquirrel here. I am a solo developer working on DeskFlow, a web-based visual planner for desk setups and cable routing.&lt;/p&gt;

&lt;p&gt;I usually code late at night after putting my kid to bed. Recently, I realized my equipment library was heavily biased towards Macbooks and just a few generic monitors. To make the tool actually useful for planning real-world setups, I just pushed a quick database update adding 11 highly requested items.&lt;/p&gt;

&lt;p&gt;Here is what just dropped into the library:&lt;/p&gt;

&lt;p&gt;Mice&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logitech MX Master 3S&lt;/li&gt;
&lt;li&gt;Apple Magic Mouse&lt;/li&gt;
&lt;li&gt;Razer DeathAdder V3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Speakers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sonos Era 100&lt;/li&gt;
&lt;li&gt;Audioengine A2+&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Monitors&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LG C3 OLED 42 inch (for the massive gaming/productivity hybrid setups)&lt;/li&gt;
&lt;li&gt;ASUS ProArt PA279CRV 27 inch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Laptops&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LG Gram 16 (2024)&lt;/li&gt;
&lt;li&gt;ASUS Zenbook 14 OLED
(Finally, some Windows love!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Power &amp;amp; Stability&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anker Power Strip (USB)&lt;/li&gt;
&lt;li&gt;APC UPS 700
(Because knowing where to hide your power strip is 90% of cable management)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is a simple content update, but having mice and power strips on the canvas really makes the setup visualization feel complete.&lt;/p&gt;

&lt;p&gt;You can check out the new items and try building your setup here: &lt;a href="https://deskflow.vercel.app" rel="noopener noreferrer"&gt;https://deskflow.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your daily driver equipment is missing from the list, drop a comment with the model name! I will prioritize adding them in the next batch.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>sideprojects</category>
      <category>desksetup</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>Making a Canvas-Based Web App Mobile Friendly (DeskFlow v1.1.8)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Fri, 01 May 2026 12:58:28 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/making-a-canvas-based-web-app-mobile-friendly-deskflow-v118-2dnk</link>
      <guid>https://dev.to/rocketsquirreldev/making-a-canvas-based-web-app-mobile-friendly-deskflow-v118-2dnk</guid>
      <description>&lt;p&gt;I'm building &lt;strong&gt;DeskFlow&lt;/strong&gt;, a visual desk setup and cable planner. Until now, it was strictly a desktop application. &lt;/p&gt;

&lt;p&gt;If you opened it on a mobile browser, it was a disaster. The left equipment panel and the right shopping list panel squeezed the central canvas into oblivion. You couldn't tap, drag, or plan anything.&lt;/p&gt;

&lt;p&gt;This weekend, I finally tackled mobile responsiveness in the v1.1.8 update. Here is a breakdown of the UX changes and the technical hurdles I ran into along the way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frx9naxyoypiddop9xrgk.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%2Frx9naxyoypiddop9xrgk.png" alt=" " width="455" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Mobile Redesign
&lt;/h3&gt;

&lt;p&gt;Since you can't cram a 3-panel layout into a 375px wide screen, I set a strict breakpoint at &lt;code&gt;650px&lt;/code&gt; and completely decoupled the mobile layout.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Canvas owns the screen:&lt;/strong&gt; The canvas now takes up 100% of the viewport.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Equipment Library:&lt;/strong&gt; Moved to a slide-out drawer accessible via a top-left hamburger menu (☰). Tapping an item drops it instantly onto the center of the canvas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shopping List:&lt;/strong&gt; Moved to a bottom sheet accessible via a top-right cart icon. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Touch Gestures:&lt;/strong&gt; Added 1-finger drag for canvas panning, and 2-finger pinch for zooming. Nodes can be tapped to select and dragged to move.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Note: The desktop experience remains exactly the same with its original 3-panel layout).&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical Challenges &amp;amp; Bug Fixes
&lt;/h3&gt;

&lt;p&gt;Making a canvas work on mobile is never just about CSS. The touch events fought me every step of the way.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. The Pinch-to-Zoom Jumping Bug
&lt;/h4&gt;

&lt;p&gt;When I first implemented the 2-finger pinch-to-zoom, the canvas would violently jump off the screen. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cause:&lt;/strong&gt; When two fingers are moving on the screen, the browser fires &lt;code&gt;touchmove&lt;/code&gt; events for &lt;em&gt;both&lt;/em&gt; touches. My panning logic was trying to calculate the delta and move the canvas based on these touches simultaneously while the zoom logic was also trying to scale the view. They collided.&lt;br&gt;
&lt;strong&gt;The fix:&lt;/strong&gt; I had to explicitly disable the panning calculation the moment &lt;code&gt;e.touches.length &amp;gt; 1&lt;/code&gt; is detected. Pan logic only runs for single touches.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. The Touch-Absorption Bug
&lt;/h4&gt;

&lt;p&gt;On mobile, users couldn't tap or drag the equipment nodes at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cause:&lt;/strong&gt; In desktop mode, when "Pan Mode" is active, I place a transparent overlay layer on top of the canvas to catch mouse drags so they don't accidentally select elements underneath. On mobile, this layer was constantly absorbing all &lt;code&gt;touchstart&lt;/code&gt; events, making the nodes underneath completely unresponsive.&lt;br&gt;
&lt;strong&gt;The fix:&lt;/strong&gt; I disabled this specific interaction layer on mobile devices, allowing the touch events to safely reach the nodes for tapping and dragging, while handling canvas panning directly on the background container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it out
&lt;/h3&gt;

&lt;p&gt;You can check out the mobile experience right from your phone without any installations. It's super handy if you are at a store and need to quickly check if a specific USB-C hub has the right ports for your layout.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Live App:&lt;/strong&gt; &lt;a href="https://deskflow.vercel.app" rel="noopener noreferrer"&gt;https://deskflow.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've built interactive canvas apps for mobile, I'd love to hear how you handled complex touch events!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ux</category>
      <category>frontend</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>[x509Lab]Generating &amp; Parsing CSRs in the Browser (No OpenSSL required) - x509Lab v1.4.0</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Wed, 29 Apr 2026 13:39:41 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/x509labgenerating-parsing-csrs-in-the-browser-no-openssl-required-x509lab-v140-46h5</link>
      <guid>https://dev.to/rocketsquirreldev/x509labgenerating-parsing-csrs-in-the-browser-no-openssl-required-x509lab-v140-46h5</guid>
      <description>&lt;p&gt;Hi everyone! I am an embedded developer by day, and an indie hacker by night. I'm building &lt;strong&gt;x509Lab&lt;/strong&gt;, a purely client-side visual tool for managing certificate chains. &lt;/p&gt;

&lt;p&gt;Today I’m releasing a pretty heavy feature update: &lt;strong&gt;CSR (Certificate Signing Request) Generation &amp;amp; Parsing.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pain Point
&lt;/h3&gt;

&lt;p&gt;Usually, creating a CSR involves opening a terminal and typing something like this:&lt;br&gt;
&lt;code&gt;openssl req -new -key private.key -out request.csr&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then you have to remember which flags to pass for Subject Alternative Names (SANs) or specific Key Usages. To check if you did it right, you have to run &lt;code&gt;openssl req -text -noout -in request.csr&lt;/code&gt;. It's tedious.&lt;/p&gt;

&lt;p&gt;x509Lab now solves this visually in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature 1: Generate CSR
&lt;/h3&gt;

&lt;p&gt;Click the 📄 &lt;strong&gt;CSR&lt;/strong&gt; button in the top toolbar to open the new modal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8k0jlk8r51fb70sx3s9r.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%2F8k0jlk8r51fb70sx3s9r.png" alt=" " width="674" height="979"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve added comprehensive Subject fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CN&lt;/code&gt; (Common Name)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;O&lt;/code&gt; (Organization)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OU&lt;/code&gt; (Org Unit)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C&lt;/code&gt;, &lt;code&gt;ST&lt;/code&gt;, &lt;code&gt;L&lt;/code&gt; (Location data)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SAN&lt;/code&gt; (DNS / IP)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the real highlight is the &lt;strong&gt;Key Usage &amp;amp; Extended Key Usage (EKU)&lt;/strong&gt; checkboxes. &lt;/p&gt;

&lt;h4&gt;
  
  
  Not just for web servers (Great for IoT/ECU)
&lt;/h4&gt;

&lt;p&gt;Since my day job involves automotive software, I wanted to make sure this tool could handle IoT and vehicle ECU PKI scenarios. &lt;/p&gt;

&lt;p&gt;By setting specific fields like &lt;code&gt;OU = ChassisControl&lt;/code&gt; and selecting &lt;code&gt;clientAuth&lt;/code&gt; and &lt;code&gt;codeSigning&lt;/code&gt; in the EKU section, you can generate CSRs perfectly suited for vehicle OTA updates or V2X infrastructure testing. &lt;/p&gt;

&lt;h3&gt;
  
  
  Feature 2: Parse CSR
&lt;/h3&gt;

&lt;p&gt;Generating is only half the battle. If you switch to the &lt;strong&gt;Parse CSR&lt;/strong&gt; tab, you can paste any existing &lt;code&gt;.csr&lt;/code&gt; PEM string or upload a file. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F62xzldspwtxx8ruijwpy.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%2F62xzldspwtxx8ruijwpy.png" alt=" " width="670" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app instantly decodes it and displays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The full Subject DN&lt;/li&gt;
&lt;li&gt;The Signature Algorithm&lt;/li&gt;
&lt;li&gt;SAN list&lt;/li&gt;
&lt;li&gt;Key Usage / EKU extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It completely replaces the need to run the &lt;code&gt;-text&lt;/code&gt; OpenSSL command just to peek inside a CSR file.&lt;/p&gt;

&lt;h3&gt;
  
  
  100% Secure &amp;amp; Client-Side
&lt;/h3&gt;

&lt;p&gt;Just like the rest of x509Lab, everything runs on the &lt;strong&gt;Web Crypto API&lt;/strong&gt;. No data, private keys, or CSRs are ever transmitted to a backend server. &lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Try it live here:&lt;/strong&gt; &lt;a href="https://x509lab.vercel.app" rel="noopener noreferrer"&gt;https://x509lab.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know if you run into any bugs or have feature requests!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>openssl</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>[DeskFlow]Solving the 'Lost in Canvas' UX problem in my Flutter Web app (DeskFlow v1.1.7)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Thu, 23 Apr 2026 13:19:10 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/deskflowsolving-the-lost-in-canvas-ux-problem-in-my-flutter-web-app-deskflow-v117-1ac0</link>
      <guid>https://dev.to/rocketsquirreldev/deskflowsolving-the-lost-in-canvas-ux-problem-in-my-flutter-web-app-deskflow-v117-1ac0</guid>
      <description>&lt;p&gt;I am building &lt;strong&gt;DeskFlow&lt;/strong&gt;, a visual planner for desk setups and cable management running on Flutter Web. &lt;/p&gt;

&lt;p&gt;In my last update, I expanded the canvas size to a massive 5000x5000 pixels so users could comfortably plan huge multi-monitor setups. But fixing one UX problem created another: users (including myself) started getting lost in the void. If you panned too far away from your hardware nodes, finding them again involved a lot of frustrating scrolling.&lt;/p&gt;

&lt;p&gt;To fix this, I released v1.1.7 today, focusing entirely on spatial navigation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth83u6msm47q7eyjshg1.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%2Fth83u6msm47q7eyjshg1.png" alt=" " width="449" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Canvas Minimap
&lt;/h3&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%2Fuigczoc29g66as5tqjul.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%2Fuigczoc29g66as5tqjul.png" alt=" " width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I added a minimap overlay in the bottom-left corner. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It represents all your active hardware nodes as cyan blocks.&lt;/li&gt;
&lt;li&gt;The white rectangle represents your current viewport.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click-to-jump:&lt;/strong&gt; You can click anywhere on the minimap to instantly pan the canvas to that exact location. No more aimless scrolling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Fit to Content (The 'F' Key)
&lt;/h3&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%2Ffwb11d9uzh1n2jdfx4jx.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%2Ffwb11d9uzh1n2jdfx4jx.png" alt=" " width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the feature I end up using the most. When you are zoomed in routing a specific USB-C cable and want to see the whole picture again, manually zooming out is tedious.&lt;/p&gt;

&lt;p&gt;Now, you can just press the &lt;strong&gt;&lt;code&gt;F&lt;/code&gt; key&lt;/strong&gt; (or click the bottom-right bounding box icon). The app calculates the bounding box of all active nodes and automatically adjusts the zoom and pan to fit everything perfectly in the center of your screen. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmggnq2auyd87v2extx1t.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%2Fmggnq2auyd87v2extx1t.png" alt=" " width="683" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Workflow
&lt;/h3&gt;

&lt;p&gt;The UX loop is now incredibly fluid:&lt;br&gt;
Hit &lt;code&gt;F&lt;/code&gt; to see the entire setup -&amp;gt; Click the Minimap to dive into a specific hub -&amp;gt; Route the cables -&amp;gt; Hit &lt;code&gt;F&lt;/code&gt; to zoom back out. &lt;/p&gt;

&lt;p&gt;If you are building a canvas-based app in Flutter or React, I highly recommend implementing a Fit-to-Content function early on. It saves so much user frustration.&lt;/p&gt;

&lt;p&gt;Try out the new navigation directly in your browser:&lt;br&gt;
🔗 &lt;strong&gt;&lt;a href="https://deskflow-gold.vercel.app/" rel="noopener noreferrer"&gt;https://deskflow-gold.vercel.app/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let me know what you think of the UX flow!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>flutter</category>
      <category>ux</category>
      <category>indiehackers</category>
    </item>
    <item>
      <title>[x509Lab]Sign new Leaf certificates with your existing Root CA directly in the browser (x509Lab v1.3.0)</title>
      <dc:creator>rocketsquirreldev</dc:creator>
      <pubDate>Tue, 21 Apr 2026 13:36:46 +0000</pubDate>
      <link>https://dev.to/rocketsquirreldev/x509labsign-new-leaf-certificates-with-your-existing-root-ca-directly-in-the-browser-x509lab-4g45</link>
      <guid>https://dev.to/rocketsquirreldev/x509labsign-new-leaf-certificates-with-your-existing-root-ca-directly-in-the-browser-x509lab-4g45</guid>
      <description>&lt;p&gt;Hey everyone. I'm building &lt;strong&gt;x509Lab&lt;/strong&gt;, a purely client-side web tool for visualizing and generating certificate chains. I usually work on this late at night after putting my kid to sleep, so I try to focus on fixing real annoyances I face during my day job.&lt;/p&gt;

&lt;p&gt;A huge pain point in the previous version was that whenever you hit the &lt;code&gt;Generate&lt;/code&gt; button, the app would blindly generate brand new keys and certificates for the entire tree. &lt;/p&gt;

&lt;p&gt;But what if you already have a Root CA and an Intermediate CA, and you just want to generate a new Leaf certificate signed by that existing Intermediate CA? &lt;/p&gt;

&lt;p&gt;With the new &lt;strong&gt;v1.3.0 update&lt;/strong&gt;, you can finally do exactly that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwh82lnwj42n2t2wh6ke9.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%2Fwh82lnwj42n2t2wh6ke9.png" alt=" " width="480" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use the selective signing feature
&lt;/h3&gt;

&lt;p&gt;The workflow is designed to be as frictionless as possible.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;First&lt;/strong&gt;, build your tree on the canvas (e.g., &lt;code&gt;Root -&amp;gt; Intermediate -&amp;gt; Leaf&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second&lt;/strong&gt;, upload your existing certificate PEM files to the Root and Intermediate nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Third&lt;/strong&gt;, you will notice a new &lt;code&gt;[+ Add Key]&lt;/code&gt; button appears on nodes that have a certificate loaded. Click it to provide the matching Private Key.&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%2F4ho7ezuo3ik7dykay1qu.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%2F4ho7ezuo3ik7dykay1qu.png" alt=" " width="800" height="781"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Finally&lt;/strong&gt;, hit &lt;code&gt;Generate Certs&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The app will now recognize that the upper nodes already have their cryptographic material. It will skip generating them and only generate the new Leaf certificate, automatically signing it using the Intermediate CA's private key you provided.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual status in the generation modal
&lt;/h3&gt;

&lt;p&gt;To prevent confusion when dealing with larger chains, the Generate modal now uses a simple color-coded status system:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5lt40roofwfhcv60mubq.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%2F5lt40roofwfhcv60mubq.png" alt=" " width="521" height="846"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;Green:&lt;/strong&gt; The node has both a certificate and a private key. It will be skipped during generation but used for signing downstream.&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;Yellow:&lt;/strong&gt; The node has a certificate but is missing a private key. You need to add it if you want it to sign the nodes below it.&lt;/li&gt;
&lt;li&gt;⚪ &lt;strong&gt;Default/Gray:&lt;/strong&gt; No certificate exists. The app will generate a fresh one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can even add the missing private keys directly from inside the modal if you see a yellow warning, saving you a few clicks.&lt;/p&gt;

&lt;h3&gt;
  
  
  A quick note on security
&lt;/h3&gt;

&lt;p&gt;I know that pasting a Private Key into a web browser sounds like a terrible idea for any security or infra engineer. &lt;/p&gt;

&lt;p&gt;Please rest assured that x509Lab is a &lt;strong&gt;100% client-side application&lt;/strong&gt;. There is no backend server. Your private keys never leave your machine; they are only stored temporarily in your browser's memory to perform the Web Crypto API signing operations and are completely wiped the moment you close or refresh the tab.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;You can try it out for free here:&lt;/strong&gt; &lt;a href="https://x509lab.vercel.app" rel="noopener noreferrer"&gt;https://x509lab.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this helps you debug your mTLS setups or saves you from digging through OpenSSL man pages, let me know. Feedback and feature requests are always welcome in the comments.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>security</category>
      <category>tools</category>
      <category>indiehackers</category>
    </item>
  </channel>
</rss>
