<?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: kandz</title>
    <description>The latest articles on DEV Community by kandz (@kandz).</description>
    <link>https://dev.to/kandz</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%2F4010024%2Fba5408f9-0a6c-4392-8632-b33b6c9bb4df.jpg</url>
      <title>DEV Community: kandz</title>
      <link>https://dev.to/kandz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kandz"/>
    <language>en</language>
    <item>
      <title>CSS Box Shadow Layers: How to Create Realistic Depth</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Thu, 08 Oct 2026 05:48:45 +0000</pubDate>
      <link>https://dev.to/kandz/css-box-shadow-layers-how-to-create-realistic-depth-2g2b</link>
      <guid>https://dev.to/kandz/css-box-shadow-layers-how-to-create-realistic-depth-2g2b</guid>
      <description>&lt;p&gt;One box-shadow is easy. Layering multiple shadows to create real depth? That's where it gets messy.&lt;/p&gt;

&lt;p&gt;A single shadow looks flat and artificial. Real-world shadows have multiple penumbras — closer to the object, darker and sharper; further away, softer and lighter.&lt;/p&gt;

&lt;p&gt;In this guide, we'll break down how to stack shadows properly, why layering works, and the gotchas that trip most developers up.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Basic Syntax
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;box-shadow&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;offset-x&lt;/span&gt; &lt;span class="nt"&gt;offset-y&lt;/span&gt; &lt;span class="nt"&gt;blur&lt;/span&gt; &lt;span class="nt"&gt;spread&lt;/span&gt; &lt;span class="nt"&gt;color&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;offset-x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Horizontal shift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;offset-y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vertical shift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;blur&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Softness of the shadow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;spread&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Expands or shrinks the shadow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;color&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shadow color (use rgba for opacity)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.1&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;This creates a subtle elevation effect.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layering Multiple Shadows
&lt;/h2&gt;

&lt;p&gt;The real power comes from stacking shadows. Separate each layer with a comma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.07&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;Each layer adds depth. The cumulative effect looks like real elevation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Layering Works
&lt;/h2&gt;

&lt;p&gt;Real-world shadows aren't a single blur. They're a gradient of penumbras.&lt;/p&gt;

&lt;p&gt;By stacking shadows with increasing blur and offset, you simulate physical behavior. The result is smooth, realistic, and professional.&lt;/p&gt;




&lt;h2&gt;
  
  
  Inset Shadows
&lt;/h2&gt;

&lt;p&gt;Add &lt;code&gt;inset&lt;/code&gt; to place the shadow inside the element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.pressed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.2&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;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input fields&lt;/li&gt;
&lt;li&gt;Pressed buttons&lt;/li&gt;
&lt;li&gt;Neumorphic designs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Gotchas
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Too harsh&lt;/td&gt;
&lt;td&gt;Use rgba with low opacity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Clips at edges&lt;/td&gt;
&lt;td&gt;Set &lt;code&gt;overflow: visible&lt;/code&gt; on parent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Reduce blur and layers on mobile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dark mode&lt;/td&gt;
&lt;td&gt;Use dark rgba, not pure black&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Performance Considerations
&lt;/h2&gt;

&lt;p&gt;Layered shadows can impact rendering performance, especially on mobile devices. Keep these in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Limit layers&lt;/strong&gt; — 3-4 shadows is usually enough&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce blur radius&lt;/strong&gt; on mobile&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid animating shadows&lt;/strong&gt; — expensive repaints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;will-change: box-shadow&lt;/code&gt;&lt;/strong&gt; sparingly&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prototyping Visually
&lt;/h2&gt;

&lt;p&gt;Writing layered shadows by hand is tedious. You guess values, reload, adjust, repeat.&lt;/p&gt;

&lt;p&gt;I built a free CSS Box Shadow Layers Designer that lets you stack shadows visually and copy the CSS instantly.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://tools.kandz.me/box-shadow-layers" rel="noopener noreferrer"&gt;tools.kandz.me/box-shadow-layers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;100% client-side. Nothing uploaded.&lt;/p&gt;




&lt;p&gt;What's your approach to elevation shadows? Do you layer them or use a single shadow? Let me know in the comments.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>design</category>
    </item>
    <item>
      <title>CSS Clip-Path: Cropping Images to Any Shape</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Thu, 01 Oct 2026 06:26:15 +0000</pubDate>
      <link>https://dev.to/kandz/css-clip-path-cropping-images-to-any-shape-1f5p</link>
      <guid>https://dev.to/kandz/css-clip-path-cropping-images-to-any-shape-1f5p</guid>
      <description>&lt;p&gt;CSS &lt;code&gt;clip-path&lt;/code&gt; is one of the most underused properties in modern web design. It lets you crop any element — images, divs, text — into circles, polygons, ellipses, or fully custom shapes without touching the original asset.&lt;/p&gt;

&lt;p&gt;The problem? Writing polygon coordinates by hand is tedious. You guess each point. You reload. You adjust. You guess again.&lt;/p&gt;

&lt;p&gt;In this guide, we'll break down how &lt;code&gt;clip-path&lt;/code&gt; works, the different shape functions, and how to prototype shapes without losing your mind.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is clip-path?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;clip-path&lt;/code&gt; creates a clipping region. Anything inside the region is visible. Anything outside is hidden.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.clipped&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The element stays the same size. The image data stays intact. Only the visible area changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Four Shape Functions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;circle()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Creates a circular clip.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.circle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&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;ul&gt;
&lt;li&gt;
&lt;code&gt;50%&lt;/code&gt; — the radius&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;at 50% 50%&lt;/code&gt; — the center point&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also use absolute units:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.circle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100px&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="nb"&gt;center&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;
  
  
  2. &lt;code&gt;ellipse()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Creates an oval clip.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.ellipse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ellipse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;40%&lt;/span&gt; &lt;span class="m"&gt;60%&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two values are the horizontal and vertical radii.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;inset()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Creates a rectangular clip with optional rounded corners.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.inset&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10%&lt;/span&gt; &lt;span class="m"&gt;20%&lt;/span&gt; &lt;span class="m"&gt;10%&lt;/span&gt; &lt;span class="m"&gt;20%&lt;/span&gt; &lt;span class="n"&gt;round&lt;/span&gt; &lt;span class="m"&gt;20px&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;Order: top, right, bottom, left. The &lt;code&gt;round&lt;/code&gt; keyword adds border-radius to the clip.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;code&gt;polygon()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The most powerful option. You define every vertex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.triangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;polygon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0%&lt;/span&gt; &lt;span class="m"&gt;100%&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;Each pair of values is an x/y coordinate. The shape is drawn by connecting them in order.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Shape&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Circular avatars&lt;/td&gt;
&lt;td&gt;&lt;code&gt;circle(50%)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hexagonal cards&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;polygon()&lt;/code&gt; with 6 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diagonal section dividers&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;polygon()&lt;/code&gt; with 4 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom image masks&lt;/td&gt;
&lt;td&gt;Any polygon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Star ratings&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;polygon()&lt;/code&gt; with 10 points&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The Hard Part: Polygon Coordinates
&lt;/h2&gt;

&lt;p&gt;A simple triangle is easy. A hexagon is manageable. A 12-point star? You're guessing.&lt;/p&gt;

&lt;p&gt;The typical workflow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write polygon coordinates&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;li&gt;Reload browser&lt;/li&gt;
&lt;li&gt;Realize one point is off&lt;/li&gt;
&lt;li&gt;Adjust&lt;/li&gt;
&lt;li&gt;Reload&lt;/li&gt;
&lt;li&gt;Repeat&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is slow, frustrating, and error-prone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Animating Clip-Path
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;clip-path&lt;/code&gt; is animatable. You can transition between shapes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30%&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clip-path&lt;/span&gt; &lt;span class="m"&gt;0.5s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.card&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;70%&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser interpolates between the two shapes — but only if both use the same function and the same number of points.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common gotcha:&lt;/strong&gt; You can't animate from &lt;code&gt;circle()&lt;/code&gt; to &lt;code&gt;polygon()&lt;/code&gt;. They must match.&lt;/p&gt;




&lt;h2&gt;
  
  
  Browser Support
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;clip-path&lt;/code&gt; is widely supported in modern browsers. &lt;code&gt;polygon()&lt;/code&gt;, &lt;code&gt;circle()&lt;/code&gt;, and &lt;code&gt;ellipse()&lt;/code&gt; work in Chrome, Firefox, Safari, and Edge.&lt;/p&gt;

&lt;p&gt;Older browsers may need the &lt;code&gt;-webkit-&lt;/code&gt; prefix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.clipped&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;clip-path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Prototyping Visually
&lt;/h2&gt;

&lt;p&gt;If you're building shapes regularly, writing coordinates by hand doesn't scale. You need a visual editor that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shows the image with draggable handles&lt;/li&gt;
&lt;li&gt;Updates the clip-path live&lt;/li&gt;
&lt;li&gt;Exports clean CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built a free CSS Clip-Path Image Cropper that does exactly this. Load an image, drag points, choose between polygon/circle/ellipse, and copy the CSS.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://tools.kandz.me/clip-path-cropper" rel="noopener noreferrer"&gt;https://tools.kandz.me/clip-path-cropper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;100% client-side. Nothing uploaded.&lt;/p&gt;




&lt;p&gt;What's your experience with &lt;code&gt;clip-path&lt;/code&gt;? Do you use it for simple shapes or complex masks? Let me know in the comments.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>design</category>
    </item>
    <item>
      <title>How to Filter CSV Columns Without Writing Code</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Thu, 24 Sep 2026 08:33:54 +0000</pubDate>
      <link>https://dev.to/kandz/how-to-filter-csv-columns-without-writing-code-25da</link>
      <guid>https://dev.to/kandz/how-to-filter-csv-columns-without-writing-code-25da</guid>
      <description>&lt;p&gt;CSV files are everywhere. Export from a database, download from a dashboard, grab from an API — it's always CSV.&lt;/p&gt;

&lt;p&gt;The problem: most CSV files have more columns than you need.&lt;/p&gt;

&lt;p&gt;You open it in Excel. You scroll. You select columns. You delete. You reorder. You export. Every single time.&lt;/p&gt;

&lt;p&gt;Let's fix that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding CSV Structure
&lt;/h2&gt;

&lt;p&gt;A CSV file is plain text. Each line is a row. Commas separate columns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csvs"&gt;&lt;code&gt;&lt;span class="k"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;city&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;salary&lt;/span&gt;
&lt;span class="k"&gt;John&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;NYC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;50000&lt;/span&gt;
&lt;span class="k"&gt;Jane&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;LA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;62000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first row is the header — it tells you what each column represents. Everything after is data.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Manual Way (Don't Do This)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open CSV in spreadsheet app&lt;/li&gt;
&lt;li&gt;Find the columns you want&lt;/li&gt;
&lt;li&gt;Delete the ones you don't&lt;/li&gt;
&lt;li&gt;Reorder if needed&lt;/li&gt;
&lt;li&gt;Export&lt;/li&gt;
&lt;li&gt;Repeat next time&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works once. It's painful at scale.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Python with pandas:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&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;salary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="n"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;filtered.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JavaScript with PapaParse:&lt;/strong&gt;&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;import&lt;/span&gt; &lt;span class="nx"&gt;Papa&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;papaparse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Papa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csvText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;salary&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both work. Both require setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  The No-Code Way
&lt;/h2&gt;

&lt;p&gt;I built a free CSV Column Filter that runs entirely in your browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load any CSV file&lt;/li&gt;
&lt;li&gt;See all columns&lt;/li&gt;
&lt;li&gt;Select, deselect, and reorder visually&lt;/li&gt;
&lt;li&gt;Export clean CSV instantly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it's useful:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No installation&lt;/li&gt;
&lt;li&gt;No upload (100% client-side)&lt;/li&gt;
&lt;li&gt;Works with any CSV&lt;/li&gt;
&lt;li&gt;Fast&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Gotchas
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Column names with spaces&lt;/td&gt;
&lt;td&gt;Quote them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empty cells&lt;/td&gt;
&lt;td&gt;Watch for column shift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Line endings&lt;/td&gt;
&lt;td&gt;Handle &lt;code&gt;\r\n&lt;/code&gt; vs &lt;code&gt;\n&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BOM at start&lt;/td&gt;
&lt;td&gt;Strip it before parsing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tools.kandz.me/csv-column-filter" rel="noopener noreferrer"&gt;https://tools.kandz.me/csv-column-filter&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;What's your CSV workflow? Do you filter columns often? Let me know in the comments.&lt;/p&gt;

</description>
      <category>csv</category>
      <category>data</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Understanding CSS Flexbox Wrap</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Thu, 17 Sep 2026 07:33:00 +0000</pubDate>
      <link>https://dev.to/kandz/understanding-css-flexbox-wrap-1bh3</link>
      <guid>https://dev.to/kandz/understanding-css-flexbox-wrap-1bh3</guid>
      <description>&lt;p&gt;Flexbox is one of those things that seems simple until it doesn't work. You set &lt;code&gt;flex-wrap: wrap&lt;/code&gt; and expect items to wrap. Then they don't. Or they wrap but leave weird gaps. Or &lt;code&gt;wrap-reverse&lt;/code&gt; flips things in ways you didn't expect.&lt;/p&gt;

&lt;p&gt;Let's break down how &lt;code&gt;flex-wrap&lt;/code&gt; actually works.&lt;/p&gt;




&lt;h2&gt;
  
  
  What flex-wrap Does
&lt;/h2&gt;

&lt;p&gt;By default, flexbox tries to fit everything on a single line. &lt;code&gt;flex-wrap&lt;/code&gt; controls what happens when items exceed the container width.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The three values:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;nowrap&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;All items on one line. Overflow if needed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wrap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Items break into multiple lines.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wrap-reverse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Same as wrap, but lines stack in reverse order.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Why Items Don't Wrap (Even with flex-wrap: wrap)
&lt;/h2&gt;

&lt;p&gt;The most common problem: you set &lt;code&gt;flex-wrap: wrap&lt;/code&gt; but items still overflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cause:&lt;/strong&gt; &lt;code&gt;min-width: auto&lt;/code&gt; on flex items.&lt;/p&gt;

&lt;p&gt;By default, flex items refuse to shrink below their content's natural width. A long word, an image, or a fixed-width element can force the item wider than its container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.flex-item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows items to shrink so wrapping can occur.&lt;/p&gt;




&lt;h2&gt;
  
  
  The align-content Trap
&lt;/h2&gt;

&lt;p&gt;If you have a fixed height on the container and use &lt;code&gt;flex-wrap: wrap&lt;/code&gt;, you might see unexpected gaps between rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cause:&lt;/strong&gt; &lt;code&gt;align-content&lt;/code&gt; defaults to &lt;code&gt;stretch&lt;/code&gt;, which distributes lines evenly to fill the container's height.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.flex-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;align-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  wrap-reverse Explained
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;wrap-reverse&lt;/code&gt; does exactly what it says: wraps in reverse. The cross-start and cross-end directions are swapped. This is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bottom-up layouts&lt;/li&gt;
&lt;li&gt;Certain animation effects&lt;/li&gt;
&lt;li&gt;Right-to-left wrapping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it's confusing because the visual order doesn't match the DOM order.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Flexbox Wrap Visually
&lt;/h2&gt;

&lt;p&gt;If you want to see how &lt;code&gt;wrap&lt;/code&gt;, &lt;code&gt;wrap-reverse&lt;/code&gt;, and alignment constraints distribute items without writing code, I built a free CSS Flexbox Wrap Simulator. It runs 100% client-side:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://tools.kandz.me/flexbox-wrap" rel="noopener noreferrer"&gt;https://tools.kandz.me/flexbox-wrap&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;What's your biggest flexbox frustration? Let me know in the comments.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>design</category>
    </item>
    <item>
      <title>Understanding SVG ViewBox Coordinates</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Sun, 13 Sep 2026 09:44:20 +0000</pubDate>
      <link>https://dev.to/kandz/understanding-svg-viewbox-coordinates-854</link>
      <guid>https://dev.to/kandz/understanding-svg-viewbox-coordinates-854</guid>
      <description>&lt;p&gt;Debugging SVG viewBox coordinates by hand is a nightmare.&lt;/p&gt;

&lt;p&gt;You open an SVG file. You need to know where a specific shape sits. You start counting pixels. You guess. You're wrong. You start over.&lt;/p&gt;

&lt;p&gt;Let's fix that.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a ViewBox?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;viewBox&lt;/code&gt; attribute defines the coordinate system for an SVG. It has four values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;viewBox="min-x min-y width height"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, &lt;code&gt;viewBox="0 0 100 100"&lt;/code&gt; means the SVG uses a 100x100 coordinate system starting from (0,0).&lt;/p&gt;




&lt;h2&gt;
  
  
  The Two Coordinate Systems
&lt;/h2&gt;

&lt;p&gt;SVG has two coordinate systems working together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;External size&lt;/strong&gt; — controlled by width/height attributes or CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal coordinate system&lt;/strong&gt; — defined by viewBox&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you set &lt;code&gt;viewBox="0 0 100 100"&lt;/code&gt; on an SVG that's 200x200px, the 100x100 user unit area is stretched to fit the 200x200 viewport. Each user unit becomes 2 screen pixels.&lt;/p&gt;




&lt;h2&gt;
  
  
  Moving the ViewBox
&lt;/h2&gt;

&lt;p&gt;Changing the &lt;code&gt;min-x&lt;/code&gt; and &lt;code&gt;min-y&lt;/code&gt; values moves the viewBox within the canvas. As one Stack Overflow user explained:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Conceptualize the viewBox as defining a transparent window in an opaque layer above the SVG canvas. When altering the viewBox attribute, you move the 'window' to the right without affecting the canvas — so your graphics move left relative to the 'window'."&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Zooming with ViewBox
&lt;/h2&gt;

&lt;p&gt;The width and height values control zoom. If your viewport is 300px wide but your viewBox width is 600px, you're seeing 600px of canvas squeezed into 300px — that's zooming out.&lt;/p&gt;




&lt;h2&gt;
  
  
  The preserveAspectRatio Attribute
&lt;/h2&gt;

&lt;p&gt;When the viewBox aspect ratio doesn't match the viewport, &lt;code&gt;preserveAspectRatio&lt;/code&gt; controls how the content is scaled and positioned. The default is &lt;code&gt;xMidYMid meet&lt;/code&gt; which centers the content and ensures the entire viewBox is visible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Finding Coordinates in Practice
&lt;/h2&gt;

&lt;p&gt;When you're editing an SVG, you often need to know the exact coordinates of a shape within the viewBox. The &lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt; has &lt;code&gt;cx&lt;/code&gt; and &lt;code&gt;cy&lt;/code&gt;. The &lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; has raw coordinate data. The &lt;code&gt;&amp;lt;rect&amp;gt;&lt;/code&gt; has &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt;, and &lt;code&gt;height&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finding those values manually is tedious. And when transforms are involved, it gets worse.&lt;/p&gt;

&lt;p&gt;If you want to visualize viewBox boundaries and extract shape coordinates without guessing, I built a free tool that does exactly this:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://tools.kandz.me/svg-viewbox-finder" rel="noopener noreferrer"&gt;https://tools.kandz.me/svg-viewbox-finder&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;What's your experience with SVG viewBox? Do you find it intuitive or confusing? Let me know in the comments.&lt;/p&gt;

</description>
      <category>svg</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>design</category>
    </item>
    <item>
      <title>Converting TSV to YAML: A Guide to Reliable Data Serialization</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Wed, 09 Sep 2026 08:41:51 +0000</pubDate>
      <link>https://dev.to/kandz/converting-tsv-to-yaml-a-guide-to-reliable-data-serialization-113j</link>
      <guid>https://dev.to/kandz/converting-tsv-to-yaml-a-guide-to-reliable-data-serialization-113j</guid>
      <description>&lt;p&gt;When working with configuration management systems like Ansible, Kubernetes, or Docker Compose, YAML is the standard. But data often starts in spreadsheets, CSV exports, or tab-separated values (TSV) from databases.&lt;/p&gt;

&lt;p&gt;Manually converting TSV to YAML is error-prone. A single misplaced tab, an unescaped colon, or a missing hyphen can break your entire configuration.&lt;/p&gt;

&lt;p&gt;In this guide, I'll walk through how to convert TSV data to YAML reliably.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Understanding TSV and YAML
&lt;/h2&gt;

&lt;p&gt;TSV (Tab-Separated Values) is a simple file format where each row is a record and columns are separated by tabs. It's commonly exported from Excel, Google Sheets, and SQL databases.&lt;/p&gt;

&lt;p&gt;YAML (YAML Ain't Markup Language) is a human-readable data serialization format. It uses indentation to represent hierarchy, making it ideal for configuration files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The challenge:&lt;/strong&gt; TSV is flat. YAML is hierarchical. Converting between them requires mapping columns to nested structures.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Parsing Problem
&lt;/h2&gt;

&lt;p&gt;A naive TSV parser splits each line by tabs. But this breaks when data contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty fields&lt;/li&gt;
&lt;li&gt;Values with tabs inside strings&lt;/li&gt;
&lt;li&gt;Lines with inconsistent column counts&lt;/li&gt;
&lt;li&gt;Quoted strings with embedded separators&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The correct approach:&lt;/strong&gt;&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;parseTSV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csvData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;csvData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;line&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;continue&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;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;result&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="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&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;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. Converting TSV to YAML
&lt;/h2&gt;

&lt;p&gt;Once parsed, the transformation is straightforward:&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;convertToYAML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tsvData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;string&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;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseTSV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tsvData&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;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;return&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rows&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yamlObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;records&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&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;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="nx"&gt;headers&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;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;obj&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;YAML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yamlObj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Edge Cases to Handle
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Empty rows&lt;/td&gt;
&lt;td&gt;Skip them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inconsistent columns&lt;/td&gt;
&lt;td&gt;Fill missing values with empty strings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Special characters&lt;/td&gt;
&lt;td&gt;Escape in YAML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large datasets&lt;/td&gt;
&lt;td&gt;Process in chunks to avoid memory issues&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  5. Common Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes ConfigMaps&lt;/strong&gt; – Converting spreadsheet data into ConfigMap YAML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ansible Inventory&lt;/strong&gt; – Mapping host data to inventory YAML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Compose&lt;/strong&gt; – Building compose files from service tables&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Seed Data&lt;/strong&gt; – Exporting data to YAML fixtures&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Client-Side Processing
&lt;/h2&gt;

&lt;p&gt;All parsing and conversion runs locally in your browser. Your data never leaves your device. This is critical when working with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuration files containing secrets&lt;/li&gt;
&lt;li&gt;Production database exports&lt;/li&gt;
&lt;li&gt;Internal project data&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Interactive Tool
&lt;/h2&gt;

&lt;p&gt;If you regularly convert TSV to YAML, I built a free tool that handles all these cases automatically:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;TSV to YAML Converter&lt;/strong&gt; – &lt;a href="http://tools.kandz.me/tsv-to-yaml" rel="noopener noreferrer"&gt;http://tools.kandz.me/tsv-to-yaml&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;What's your use case for converting TSV to YAML? Drop it in the comments.&lt;/p&gt;

</description>
      <category>yaml</category>
      <category>json</category>
      <category>data</category>
      <category>programming</category>
    </item>
    <item>
      <title>Designing UI Depth: Mastering the Physics of CSS Glassmorphism</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Fri, 04 Sep 2026 07:44:38 +0000</pubDate>
      <link>https://dev.to/kandz/designing-ui-depth-mastering-the-physics-of-css-glassmorphism-50ic</link>
      <guid>https://dev.to/kandz/designing-ui-depth-mastering-the-physics-of-css-glassmorphism-50ic</guid>
      <description>&lt;p&gt;User interface paradigms continuously swing between flat minimalism and layered skeuomorphism. The rise of &lt;strong&gt;Glassmorphism&lt;/strong&gt; — which simulates a translucent, frosted-glass pane floating over high-contrast background vectors — has emerged as a major design trend. When designed correctly, glassmorphism creates a beautiful sense of visual hierarchy, layering, and specular depth.&lt;/p&gt;

&lt;p&gt;However, writing production-ready glassmorphic CSS rules is not as simple as lowering element opacity. It requires a precise coordination of background refractions, border reflections, and drop shadow depths.&lt;/p&gt;

&lt;p&gt;In this technical guide, we will deconstruct the underlying CSS physics of glassmorphic layers, address critical cross-browser rendering quirks, and look at how to prototype these styles in code.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Backdrop Blurring: Filter vs. Backdrop-Filter
&lt;/h2&gt;

&lt;p&gt;The foundational element of glassmorphism is refraction — the bending of light as it passes through glass. In CSS, developers often confuse the standard &lt;code&gt;filter&lt;/code&gt; property with &lt;code&gt;backdrop-filter&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* This is NOT glassmorphism */&lt;/span&gt;
&lt;span class="nc"&gt;.broken-glass-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.2&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;
  
  
  Why this fails:
&lt;/h3&gt;

&lt;p&gt;The standard &lt;code&gt;filter: blur()&lt;/code&gt; property applies graphical filter adjustments directly to the element itself and &lt;strong&gt;all of its nested DOM children&lt;/strong&gt;. This means any paragraph text, headers, or buttons inside the card will also be blurred, rendering your copy completely illegible.&lt;/p&gt;

&lt;p&gt;To achieve frosted glass refraction, you must use the modern &lt;code&gt;backdrop-filter&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* This is true glassmorphism */&lt;/span&gt;
&lt;span class="nc"&gt;.frosted-glass-card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* Safari Vendor Prefix */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;backdrop-filter&lt;/code&gt; property applies the blurring effect strictly to the underlying graphical layers &lt;strong&gt;visible behind the element&lt;/strong&gt;, keeping the overlay content, typography, and interactive buttons razor-sharp.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cross-Browser Note&lt;/strong&gt;: Always declare &lt;code&gt;-webkit-backdrop-filter&lt;/code&gt; alongside &lt;code&gt;backdrop-filter&lt;/code&gt;. iOS Safari and macOS Safari still require the vendor prefix to render backdrop filters correctly.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Simulating Specular Reflection with Borders
&lt;/h2&gt;

&lt;p&gt;In physical spaces, glass is bounded by a specular reflection — a subtle, high-contrast gleam of light bouncing off the bevel or edge of the sheet. Without this specular highlight, glassmorphism cards look like flat, semi-opaque boxes with no physical boundaries.&lt;/p&gt;

&lt;p&gt;We can simulate this reflection in CSS by adding a thin, semi-transparent border using &lt;code&gt;rgba&lt;/code&gt; color stops:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.frosted-glass-card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-backdrop-filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c"&gt;/* Specular Highlight Edge */&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.25&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;This 1px border establishes a clean, bright, translucent edge that separates the card from busy background graphics, regardless of whether the background is dark or light.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The Role of Shadow and Contrast
&lt;/h2&gt;

&lt;p&gt;Glassmorphic elements only look convincing when there is something to distort behind them. If you place a frosted-glass card over a flat, solid-colored background, the backdrop blur has nothing to refract, and the element simply looks like a flat grey or white box.&lt;/p&gt;

&lt;p&gt;To make the refraction pop, you must design with &lt;strong&gt;contrast&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Place glass cards over bright, high-contrast, multi-colored gradients or organic geometric shapes.&lt;/li&gt;
&lt;li&gt;Implement a soft, diffuse &lt;code&gt;box-shadow&lt;/code&gt; on the card to create physical elevation:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.frosted-glass-card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="m"&gt;32px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Programmatic RGBA Hex Mapping
&lt;/h2&gt;

&lt;p&gt;When building design tools, allowing users to select solid colors via standard HTML &lt;code&gt;&amp;lt;input type="color"&amp;gt;&lt;/code&gt; pickers requires converting those hex values into raw &lt;code&gt;rgba()&lt;/code&gt; parameters programmatically in order to map custom opacity sliders.&lt;/p&gt;

&lt;p&gt;Here is a type-safe TypeScript implementation that handles the translation of 3-digit and 6-digit hex values securely:&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="cm"&gt;/**
 * Safely converts hexadecimal strings and alpha opacity into compliant RGBA parameters
 * @param hex The raw color string (e.g. "#ffffff" or "#fff")
 * @param alpha The opacity modifier between 0 and 1
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;hexToRgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#&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="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Expand 3-digit hex shorthands (e.g. "fff" -&amp;gt; "ffffff")&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;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&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="nf"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`rgba(255, 255, 255, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Safe fallback&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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;255&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;g&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;255&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`rgba(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;This converter ensures all properties run 100% locally in your browser's private memory sandbox [1]. Since no assets or styles are ever sent to an external server, your local design schemes and configurations remain completely secure [1].&lt;/p&gt;




&lt;h2&gt;
  
  
  Interactive Playground
&lt;/h2&gt;

&lt;p&gt;If you want to visually adjust backdrop blurs, slide opacities, customize borders, and copy production-ready CSS and HTML across different high-contrast canvas backdrops:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://tools.kandz.me/glassmorphism-card" rel="noopener noreferrer"&gt;CSS Glassmorphism Card Designer on Kandz.me&lt;/a&gt;&lt;/strong&gt; [1]&lt;/p&gt;

&lt;p&gt;What are your thoughts on glassmorphism? Do you find backdrop blurs performant on mobile web rendering engines? Let's discuss in the comments!&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>uidesign</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Deep Merging in JavaScript: How to Recursively Combine Objects Without Losing Nested Properties</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Mon, 31 Aug 2026 07:54:44 +0000</pubDate>
      <link>https://dev.to/kandz/deep-merging-in-javascript-how-to-recursively-combine-objects-without-losing-nested-properties-b2k</link>
      <guid>https://dev.to/kandz/deep-merging-in-javascript-how-to-recursively-combine-objects-without-losing-nested-properties-b2k</guid>
      <description>&lt;p&gt;In JavaScript and TypeScript application architecture, combining configurations, managing nested state states, or applying user overrides to default settings are standard requirements. &lt;/p&gt;

&lt;p&gt;However, many developers still fall into the trap of using shallow copy mechanisms like &lt;code&gt;Object.assign()&lt;/code&gt; or the object spread operator (&lt;code&gt;...&lt;/code&gt;). When applied to nested objects, these approaches can lead to silent data loss, state mutations, and hard-to-track runtime bugs.&lt;/p&gt;

&lt;p&gt;In this technical breakdown, we will analyze why shallow merging fails on nested structures, explore the mechanics of a recursive deep merge algorithm, and write a type-safe, non-&lt;code&gt;any&lt;/code&gt; deep merge utility in TypeScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Fallacy of Shallow Merging
&lt;/h2&gt;

&lt;p&gt;Shallow copying only copies the top-level properties of an object. If a property is a reference type (like a nested object or array), only the reference pointer is copied—not the actual nested data.&lt;/p&gt;

&lt;p&gt;Consider this common configuration scenario:&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;const&lt;/span&gt; &lt;span class="nx"&gt;defaultSettings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userOverrides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// The Shallow Merge Trap&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mergedSettings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;defaultSettings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;userOverrides&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mergedSettings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/*
Output:
{
  theme: 'light',
  api: {
    timeout: 10000
  }
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why did this fail?
&lt;/h3&gt;

&lt;p&gt;Because the spread operator performed a shallow assignment, the nested &lt;code&gt;api&lt;/code&gt; property on &lt;code&gt;userOverrides&lt;/code&gt; completely &lt;strong&gt;overwrote&lt;/strong&gt; the original &lt;code&gt;api&lt;/code&gt; object on &lt;code&gt;defaultSettings&lt;/code&gt;. As a result, the critical &lt;code&gt;endpoint&lt;/code&gt; property was completely lost.&lt;/p&gt;

&lt;p&gt;To combine nested properties rather than overwriting them, we must perform a &lt;strong&gt;Recursive Deep Merge&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The Mechanics of a Recursive Deep Merge Algorithm
&lt;/h2&gt;

&lt;p&gt;A true deep merge algorithm must recursively traverse the object trees. If both objects share a key, the algorithm must evaluate the types of their respective values:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Both values are objects&lt;/strong&gt;: Recursively call the merge function to combine their sub-properties.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Both values are arrays&lt;/strong&gt;: Decide whether to concatenate them, keep unique elements, or overwrite with the new array.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value types differ (or are primitives)&lt;/strong&gt;: Resolve the conflict by either keeping the original value or overwriting it based on a designated collision policy.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. Writing a Type-Safe Deep Merge Utility in TypeScript
&lt;/h2&gt;

&lt;p&gt;To ensure strict compiler compliance under modern TypeScript standards, we must avoid the forbidden &lt;code&gt;any&lt;/code&gt; type and build a robust, structurally typed merging engine. &lt;/p&gt;

&lt;p&gt;Here is the clean, type-safe implementation:&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="cm"&gt;/**
 * Safe helper checking if an item is a non-null, non-array object
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&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;item&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Recursively deep-merges two object trees securely
 * @param a The base target object
 * @param b The incoming override object
 * @param arrayStrategy How to handle array collisions ('concat' | 'unique' | 'replace')
 * @param conflictStrategy How to resolve primitive conflicts ('overwrite-b' | 'keep-a')
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deepMerge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;arrayStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;concat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unique&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;replace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;concat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;conflictStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;overwrite-b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keep-a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;overwrite-b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;a&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;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;valA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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;valB&lt;/span&gt; &lt;span class="o"&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;key&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="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nf"&gt;isObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valB&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Both are objects: recurse deeper&lt;/span&gt;
      &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deepMerge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;valA&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;valB&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;arrayStrategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;conflictStrategy&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;valB&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Both are arrays: apply array merging strategy&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;arrayStrategy&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;concat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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="nx"&gt;valA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;valB&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;arrayStrategy&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unique&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;valA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;valB&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&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="nx"&gt;valB&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// replace&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Primitive or mismatched types: apply conflict resolution&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;valA&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;conflictStrategy&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keep-a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;valA&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;valB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;valB&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;result&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;
  
  
  Why this structure is secure:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strong Type Assertions&lt;/strong&gt;: It uses structural record indexing (&lt;code&gt;Record&amp;lt;string, unknown&amp;gt;&lt;/code&gt;) to protect the compiler against type-erasure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictable Collisions&lt;/strong&gt;: By separating array strategies and value conflicts, the algorithm avoids random reference changes or unexpected state mutations.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Interactive Playground
&lt;/h2&gt;

&lt;p&gt;If you need to merge complex settings side-by-side, analyze conflicts, customize your array concatenation behaviors, and inspect the resulting JSON securely inside your local browser memory:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://tools.kandz.me/object-merger" rel="noopener noreferrer"&gt;JS Object Merging Utility on Kandz.me&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How do you manage nested configurations in your frameworks? Let's discuss in the comments!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Writing Secure Shell Scripts: A Guide to Auditing and Sanitizing Unsafe Bash Code</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Thu, 27 Aug 2026 10:58:13 +0000</pubDate>
      <link>https://dev.to/kandz/writing-secure-shell-scripts-a-guide-to-auditing-and-sanitizing-unsafe-bash-code-2d3h</link>
      <guid>https://dev.to/kandz/writing-secure-shell-scripts-a-guide-to-auditing-and-sanitizing-unsafe-bash-code-2d3h</guid>
      <description>&lt;p&gt;Shell scripting remains the connective tissue of modern deployment pipelines, system administration, and container orchestration. Yet, despite its ubiquity, Bash is notoriously fragile. A single unquoted variable or a missing error handling flag can result in disastrous silent failures, partial script executions, or critical security vulnerabilities.&lt;/p&gt;

&lt;p&gt;In this technical guide, we will analyze common, high-risk anti-patterns in Bash scripts, explain why standard shell environments fail silently, and demonstrate how to programmatically audit shell script structures for duplicate variables and unsafe parameters.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The High-Risk Anti-Patterns of Silent Bash Failures
&lt;/h2&gt;

&lt;p&gt;By default, Bash execution engines are designed to be permissive. Unlike strict programming environments that throw exceptions and halt execution on errors, shell scripts will happily continue executing even if a key command fails or a variable is undefined.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern A: Missing Safety Headers
&lt;/h3&gt;

&lt;p&gt;Consider this snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;TARGET_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TARGET_DIR&lt;/span&gt;&lt;span class="s2"&gt;/*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this script is executed without arguments, &lt;code&gt;TARGET_DIR&lt;/code&gt; remains an empty string. The shell expands the command to &lt;code&gt;rm -rf /*&lt;/code&gt;, which will attempt to recursively delete the host machine's root directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern B: Unquoted Variables and Word Splitting
&lt;/h3&gt;

&lt;p&gt;When you reference a variable without wrapping it in double quotes (e.g., &lt;code&gt;echo $FILE_NAME&lt;/code&gt;), the shell subjects the variable's value to &lt;strong&gt;Word Splitting&lt;/strong&gt; and &lt;strong&gt;Pathname Expansion (Globbing)&lt;/strong&gt; based on internal field separator (IFS) whitespace. If a file name contains spaces, the shell will treat it as multiple separate arguments, leading to unexpected behaviors or syntax failures in conditional tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Establishing a Strict Safety Standard
&lt;/h2&gt;

&lt;p&gt;The first step in securing any shell script is to configure a defensive execution header using the &lt;code&gt;set&lt;/code&gt; built-in utility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deconstructing the Safe Header Flags:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;set -e&lt;/code&gt; (Exit Immediately)&lt;/strong&gt;: Tells the shell to terminate the script immediately if any command exits with a non-zero status code. This prevents silent cascades where later scripts run despite previous critical dependency failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;set -u&lt;/code&gt; (Nounset)&lt;/strong&gt;: Treats any reference to an uninitialized or unbound variable as a fatal syntax error, instantly stopping execution (safeguarding against empty path expansions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;set -o pipefail&lt;/code&gt; (Pipeline Failures)&lt;/strong&gt;: Normally, a pipeline's exit status is only determined by the very last command. Using &lt;code&gt;pipefail&lt;/code&gt; ensures that if any command in a pipeline fails (e.g., &lt;code&gt;cat missing_file | grep 'pattern'&lt;/code&gt;), the entire pipeline returns a failing exit status.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Auditing Variables and Parameters in TypeScript
&lt;/h2&gt;

&lt;p&gt;To help developers proactively scan their scripts for vulnerabilities before deploying them to production, we can write a client-side parser in TypeScript that audits variables and detects common anomalies like &lt;strong&gt;duplicate declarations&lt;/strong&gt; or &lt;strong&gt;unsafe variable assignments&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Below is a robust, type-safe implementation of a static script scanner:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SanitizationReport&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;warnings&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="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Parses and audits raw Bash code for common vulnerabilities and duplicate assignments
 * @param scriptSource The raw shell script string to audit
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sanitizeBashScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scriptSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SanitizationReport&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;warnings&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;scriptSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\r?\n&lt;/span&gt;&lt;span class="sr"&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;declaredVariables&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Check for safety headers&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;lines&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="nf"&gt;trim&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="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;firstLine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;warnings&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Warning: Missing standard Shebang header (e.g., #!/bin/bash).&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scriptBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;scriptSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/#.*/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Strip comments&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;scriptBody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;set -e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;scriptBody&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;set -o pipefail&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;warnings&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Security Alert: Script lacks strict safety controls (e.g., "set -euo pipefail" is highly recommended).&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Detect variable declarations and check for duplicates&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;variableDeclarationRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;([&lt;/span&gt;&lt;span class="sr"&gt;a-zA-Z_&lt;/span&gt;&lt;span class="se"&gt;][&lt;/span&gt;&lt;span class="sr"&gt;a-zA-Z0-9_&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)\s&lt;/span&gt;&lt;span class="sr"&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;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Ignore lines that are comments or empty&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;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;continue&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;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;variableDeclarationRegex&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;match&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;match&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="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;varName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;match&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="nx"&gt;declaredVariables&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;varName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;warnings&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;`Line &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: Variable "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;varName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" is redeclared. Verify if this duplicate assignment was intentional.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;declaredVariables&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="nx"&gt;varName&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="c1"&gt;// Flag dangerous patterns like unquoted directory removals&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;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rm -rf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="sr"&gt;/rm -rf&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\$[&lt;/span&gt;&lt;span class="sr"&gt;a-zA-Z0-9_&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;(\s&lt;/span&gt;&lt;span class="sr"&gt;|$&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;warnings&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;`Line &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: Unsafe recursive removal detected. Variables in "rm -rf" should always be double-quoted to prevent root deletions.`&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;isValid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="nx"&gt;warnings&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;This secure script parser performs all structural inspections entirely client-side. Since no script payloads or deployment credentials are sent over the network, your server keys, database ports, and infrastructure parameters remain completely secure in your browser.&lt;/p&gt;




&lt;h2&gt;
  
  
  Interactive Playground
&lt;/h2&gt;

&lt;p&gt;If you want to validate your Bash scripts, automatically audit variables, strip unsafe parameters, and copy sanitized script headers, feel free to try our free developer tool:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://tools.kandz.me/bash-sanitizer" rel="noopener noreferrer"&gt;Bash Script Sanitizer on Kandz.me&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How do you secure your production shell scripts? Do you enforce strict linters in your CI/CD pipelines? Let's discuss in the comments!&lt;/p&gt;

</description>
      <category>bash</category>
      <category>devops</category>
      <category>security</category>
      <category>shell</category>
    </item>
    <item>
      <title>Mastering CSS Grid: Visual Layout Prototyping with grid-template-areas</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Sun, 23 Aug 2026 10:09:29 +0000</pubDate>
      <link>https://dev.to/kandz/mastering-css-grid-visual-layout-prototyping-with-grid-template-areas-3602</link>
      <guid>https://dev.to/kandz/mastering-css-grid-visual-layout-prototyping-with-grid-template-areas-3602</guid>
      <description>&lt;p&gt;Designing responsive web layouts has historically been a balancing act of float properties, absolute position rules, and nested flexbox containers. While CSS Grid introduced a highly structured 2D grid model, many developers still rely on manual column and row span indices (&lt;code&gt;grid-column: 1 / 3;&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;If you are looking for a more declarative, semantic, and maintainable approach to responsive layouts, &lt;strong&gt;CSS Grid Template Areas&lt;/strong&gt; (&lt;code&gt;grid-template-areas&lt;/code&gt;) is the ultimate standard.&lt;/p&gt;

&lt;p&gt;In this technical breakdown, we will deconstruct how named grid areas work, why they make media queries cleaner, and how to build a client-side visual grid layout editor in TypeScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Power of Declarative Named Grid Areas
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;grid-template-areas&lt;/code&gt; property allows you to define your layout using clear string templates. Each row in your grid is defined as a string, and each word inside that string represents a single grid cell.&lt;/p&gt;

&lt;p&gt;Consider this classic "Holy Grail" grid layout configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.grid-layout&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-areas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="s1"&gt;"header  header  header"&lt;/span&gt;
    &lt;span class="s1"&gt;"sidebar main    main"&lt;/span&gt;
    &lt;span class="s1"&gt;"sidebar footer  footer"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&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;Instead of managing mathematical indices, we assign grid areas by name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.header&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.sidebar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.main&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.footer&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;footer&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;
  
  
  Key Architectural Benefits:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-Documenting Code&lt;/strong&gt;: Your stylesheet visualizes the structural page layout directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: Your semantic HTML remains completely unaffected by layout changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Math Spans&lt;/strong&gt;: The browser automatically handles merging and spanning boundaries based on adjacent matching names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Empty Spacers Made Simple&lt;/strong&gt;: To leave a cell completely empty, you simply use a dot (&lt;code&gt;.&lt;/code&gt;) inside your template string (e.g., &lt;code&gt;"header . sidebar"&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Responsive UI Design via Simple Media Queries
&lt;/h2&gt;

&lt;p&gt;One of the greatest advantages of named grid areas is the ease of responsive design. Instead of restructuring your HTML document structure, or changing multiple columns and rows spans on individual elements, you only need to redefine the &lt;code&gt;grid-template-areas&lt;/code&gt; property on the &lt;strong&gt;parent grid container&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is how you redefine the same template structure on mobile devices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.grid-layout&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;grid-template-areas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="s1"&gt;"header"&lt;/span&gt;
      &lt;span class="s1"&gt;"main"&lt;/span&gt;
      &lt;span class="s1"&gt;"sidebar"&lt;/span&gt;
      &lt;span class="s1"&gt;"footer"&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;The browser handles repositioning the elements seamlessly.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Designing a Client-Side Grid Layout Painter in TypeScript
&lt;/h2&gt;

&lt;p&gt;To help developers build and experiment with these configurations, we developed a local client-side visual painter. &lt;/p&gt;

&lt;p&gt;We can model the grid states reactively in TypeScript. By representing the grid canvas as a flat array of cell tags corresponding to &lt;code&gt;[rowsCount * colsCount]&lt;/code&gt;, users can click cells to change their area assignments in real-time.&lt;/p&gt;

&lt;p&gt;Here is the core logic to compile the CSS string and distinct selectors:&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="cm"&gt;/**
 * Compiles a flat grid array into compliant CSS grid-template-areas strings
 * @param cells Array of area strings (e.g., ['header', 'header', 'main', ...])
 * @param rows Total rows in the layout
 * @param cols Total columns in the layout
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;compileGridTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;areaRows&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;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rowSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cols&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;rowStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rowSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cell&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;empty&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;.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cell&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;areaRows&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;`    "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;rowStr&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;areaRows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&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="cm"&gt;/**
 * Extracts unique class area selectors for layout structures
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getDistinctSelectors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&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="kr"&gt;string&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="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cells&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&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;c&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;empty&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;p&gt;This model compiles the grid definitions instantly inside your browser's private memory sandbox. This ensures maximum privacy, so your custom structures and designs are never sent to external servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Interactive Playground
&lt;/h2&gt;

&lt;p&gt;If you want to visually paint layouts, customize dimensions, define custom brush tools, and copy ready-to-use CSS and HTML, feel free to try our free developer tool:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://tools.kandz.me/grid-template-areas" rel="noopener noreferrer"&gt;CSS Grid Template Areas Visualizer on Kandz.me&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How do you manage your CSS Grid structures? Do you prefer manual span properties or named areas? Let's discuss in the comments!&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>html</category>
    </item>
    <item>
      <title>Measuring Code Quality: Building a Client-Side JavaScript Complexity &amp; Maintainability Analyzer</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Wed, 19 Aug 2026 08:24:35 +0000</pubDate>
      <link>https://dev.to/kandz/measuring-code-quality-building-a-client-side-javascript-complexity-maintainability-analyzer-5a8m</link>
      <guid>https://dev.to/kandz/measuring-code-quality-building-a-client-side-javascript-complexity-maintainability-analyzer-5a8m</guid>
      <description>&lt;p&gt;As codebases scale under aggressive product cycles, functions can easily become bloated with deeply nested loops and excessive conditional branches. This increases technical debt and makes unit testing much harder.&lt;/p&gt;

&lt;p&gt;To help developers audit their code hygiene instantly and securely, we built a &lt;strong&gt;JS Code Complexity Analyzer&lt;/strong&gt; running completely client-side. Here is a technical breakdown of how we calculated McCabe's Cyclomatic Complexity, mapped maximum nesting depths, and approximated the industry-standard Maintainability Index in the browser.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The Mathematics of Cyclomatic Complexity
&lt;/h3&gt;

&lt;p&gt;Developed by Thomas J. McCabe in 1976, &lt;strong&gt;Cyclomatic Complexity&lt;/strong&gt; measures the number of linearly independent execution paths through a program's source code. &lt;/p&gt;

&lt;p&gt;Rather than loading a heavy Abstract Syntax Tree (AST) parser in the browser, our engine performs a highly efficient, regex-based token scan. The algorithm starts with a baseline complexity score of &lt;code&gt;1&lt;/code&gt;. For each decision node or branching point detected in the code, the score increases by &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We scan lines for the following branching patterns (while ignoring matches found inside comments):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conditional branches: &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;case&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Loop structures: &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Error handling: &lt;code&gt;catch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Logical operators: &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ternary operators: &lt;code&gt;?&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A higher score indicates more independent paths, warning developers that the function requires more unit tests to cover all execution conditions.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Scanning Maximum Nesting Depth
&lt;/h3&gt;

&lt;p&gt;Nesting depth measures how deeply control structures are layered inside one another. High complexity with flat nesting is often manageable, but deeply nested code is notoriously hard to read.&lt;/p&gt;

&lt;p&gt;Our engine calculates the maximum nesting depth by scanning the brace-balance (&lt;code&gt;{&lt;/code&gt; and &lt;code&gt;}&lt;/code&gt;) of the code block sequentially. It tracks the current nesting depth in real-time, recording the maximum depth reached during the lexical scan.&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;currentDepth&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;maxDepth&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;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;currentDepth&lt;/span&gt;&lt;span class="o"&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;currentDepth&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;maxDepth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;maxDepth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentDepth&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;else&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;code&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;currentDepth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&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="nx"&gt;currentDepth&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Approximating the Maintainability Index
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Maintainability Index&lt;/strong&gt; is an industry-standard metric (ranging from 0% to 100%) indicating how easy the code is to support and modify. The classic formula balances Halstead Volume, Cyclomatic Complexity, and Source Lines of Code (SLOC).&lt;/p&gt;

&lt;p&gt;Our engine calculates a highly reliable approximation of this index using a logarithmic scale:&lt;/p&gt;

&lt;p&gt;$$\text{Maintainability Index} = 171 - (3.5 \times \ln(\text{Complexity})) - (0.23 \times \text{Complexity}) - (16.2 \times \ln(\text{SLOC}))$$&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Excellent Maintainability:&lt;/strong&gt; Scores above 75% (low complexity, short, clean).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Moderate Maintainability:&lt;/strong&gt; Scores between 50% and 75%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low Maintainability:&lt;/strong&gt; Scores below 50% (high complexity, deep nesting, long lines).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Interactive Sandbox &amp;amp; Security Hygiene
&lt;/h3&gt;

&lt;p&gt;The tool displays these metrics on a responsive dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;McCabes Complexity Score:&lt;/strong&gt; Classified by risk ratings (Low Risk &amp;lt; 10, Moderate Risk 10–15, High Risk &amp;gt; 15).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nesting Depth Counter:&lt;/strong&gt; Flags blocks nested too deeply.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SLOC Breakdown:&lt;/strong&gt; Tracks actual Source Lines of Code, comments, and blank spacer lines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Transmitting proprietary enterprise code, server router functions, or security scripts to external servers poses a severe privacy risk. By executing all static analysis, regex parsing, and index math locally inside your browser's private sandbox memory, your configurations remain completely secure.&lt;/p&gt;

&lt;p&gt;Test your custom JavaScript routines, analyze nested loops, and check your complexity scores:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Test the Live Tool:&lt;/strong&gt; &lt;a href="https://tools.kandz.me/code-complexity" rel="noopener noreferrer"&gt;https://tools.kandz.me/code-complexity&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building a High-Performance, Client-Side JSON Diff Checker Using Dynamic Programming (LCS)</title>
      <dc:creator>kandz</dc:creator>
      <pubDate>Sat, 15 Aug 2026 10:34:04 +0000</pubDate>
      <link>https://dev.to/kandz/building-a-high-performance-client-side-json-diff-checker-using-dynamic-programming-lcs-560i</link>
      <guid>https://dev.to/kandz/building-a-high-performance-client-side-json-diff-checker-using-dynamic-programming-lcs-560i</guid>
      <description>&lt;p&gt;Comparing nested JSON configuration files across builds or API revisions is a constant necessity in backend development. While standard text diffing utilities exist, semantic JSON comparison requires robust syntax validation combined with clean line-by-line alignment.&lt;/p&gt;

&lt;p&gt;To solve this, we built a secure, client-side &lt;strong&gt;JSON Diff Checker&lt;/strong&gt; that parses, formats, and compares JSON documents locally. Here is a technical breakdown of how we engineered its dynamic programming comparison engine and why local validation matters.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Architecture: JSON Parsing + LCS Line Mapping
&lt;/h3&gt;

&lt;p&gt;A high-fidelity JSON diff utility cannot simply run a raw text string comparison; doing so would highlight harmless differences like varying spacing or reordered properties as false positives. Our engine operates in two clean phases:&lt;/p&gt;

&lt;h4&gt;
  
  
  Phase 1: Semantic Standardizing
&lt;/h4&gt;

&lt;p&gt;First, both inputs are parsed safely via standard browser JSON libraries. This step validates JSON well-formedness, capturing trailing commas, mismatched braces, or double-quote syntax warnings. Once parsed, the objects are compiled back into formatted string arrays with standard 2-space indentation. This standardizes whitespace and makes comparison line-by-row predictable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Phase 2: Longest Common Subsequence (LCS)
&lt;/h4&gt;

&lt;p&gt;Second, we run a dynamic programming LCS algorithm over the standardized line arrays to find the shortest edit path. Here is how the recursive traceback matrix computes the state of each line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dynamic programming matrix initialization&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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="nf"&gt;fill&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&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="nf"&gt;fill&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="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;j&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="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leftLines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;rightLines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&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="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;j&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="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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;j&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="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;By traversing the completed matrix, the engine identifies exactly which formatted lines were &lt;strong&gt;added&lt;/strong&gt; (+), &lt;strong&gt;removed&lt;/strong&gt; (-), or &lt;strong&gt;kept unchanged&lt;/strong&gt; (➔), mapping precise line numbers to both columns.&lt;/p&gt;




&lt;h3&gt;
  
  
  Core Symmetrical Design &amp;amp; Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instant Syntax Diagnostics:&lt;/strong&gt; If either JSON input is malformed, the visualizer halts gracefully, displaying clear syntax error messages and pinpointing the structural issue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Symmetrical Layout Sizing:&lt;/strong&gt; Built with a 5-column control console on the left (for source payloads and presets) and a 7-column highlight scrollbox on the right (height restricted to 450px) to maintain a perfectly balanced layout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log Snapping with Custom Names:&lt;/strong&gt; Includes an editable configuration label so you can save your compared datasets with distinct names (e.g., "User Profile Verification") directly to your local History Log.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try out the interactive comparison sandbox, paste your configurations, and test the dynamic alignment yourself:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Test the Live Tool:&lt;/strong&gt; &lt;a href="https://tools.kandz.me/json-diff" rel="noopener noreferrer"&gt;https://tools.kandz.me/json-diff&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>json</category>
      <category>algorithms</category>
    </item>
  </channel>
</rss>
