<?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: zhihu wu</title>
    <description>The latest articles on DEV Community by zhihu wu (@zhihu_wu_dea1d82af01a04d7).</description>
    <link>https://dev.to/zhihu_wu_dea1d82af01a04d7</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%2F3921997%2Fa775d61f-ed57-461b-ac46-ed108350189e.png</url>
      <title>DEV Community: zhihu wu</title>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zhihu_wu_dea1d82af01a04d7"/>
    <language>en</language>
    <item>
      <title>URL Encoding Demystified: encodeURIComponent vs encodeURI</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Wed, 29 Jul 2026 13:08:46 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/url-encoding-demystified-encodeuricomponent-vs-encodeuri-12d3</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/url-encoding-demystified-encodeuricomponent-vs-encodeuri-12d3</guid>
      <description>&lt;p&gt;You are debugging a broken API call. The URL looks fine in your browser, but the server returns 400. You stare at the query string: &lt;code&gt;?q=hello world&amp;amp;filter=active&lt;/code&gt;. There is your problem — that space.&lt;/p&gt;

&lt;p&gt;URL encoding is one of those things every developer encounters but few fully understand. Let us fix that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Two JavaScript Functions (and Why Both Exist)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;encodeURI()&lt;/code&gt; is for &lt;strong&gt;entire URLs&lt;/strong&gt;. It preserves characters that have structural meaning: &lt;code&gt;:&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, &lt;code&gt;&amp;amp;&lt;/code&gt;, &lt;code&gt;#&lt;/code&gt;. Use it when you have a complete URL and just need to make it safe.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;encodeURIComponent()&lt;/code&gt; is for &lt;strong&gt;individual parameter values&lt;/strong&gt;. It encodes everything except &lt;code&gt;A-Z a-z 0-9 - _ . ! ~ * ' ( )&lt;/code&gt;. The &lt;code&gt;&amp;amp;&lt;/code&gt; in your filter value? Encoded. The &lt;code&gt;=&lt;/code&gt; in your base64 token? Encoded.&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="nf"&gt;encodeURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/search?q=hello world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// → "https://example.com/search?q=hello%20world"&lt;/span&gt;

&lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// → "hello%20world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule: &lt;code&gt;encodeURI()&lt;/code&gt; for the whole URL, &lt;code&gt;encodeURIComponent()&lt;/code&gt; for each parameter value. Mix them up and you either break the URL structure or leave dangerous characters unencoded.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Double-Encoding Trap
&lt;/h2&gt;

&lt;p&gt;If you encode a string that is already encoded, the &lt;code&gt;%&lt;/code&gt; signs get re-encoded to &lt;code&gt;%25&lt;/code&gt;. &lt;code&gt;hello%20world&lt;/code&gt; becomes &lt;code&gt;hello%2520world&lt;/code&gt;. The server decodes once and gets &lt;code&gt;hello%20world&lt;/code&gt; — still encoded. A second decode gives you the original, but most servers only decode once.&lt;/p&gt;

&lt;p&gt;Spot double-encoding by looking for &lt;code&gt;%25&lt;/code&gt; in your output. If you see it, decode first, then re-encode.&lt;/p&gt;

&lt;h2&gt;
  
  
  %20 vs + for Spaces
&lt;/h2&gt;

&lt;p&gt;In query strings, HTML forms use &lt;code&gt;+&lt;/code&gt; for spaces (&lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt;). In path segments, use &lt;code&gt;%20&lt;/code&gt; (RFC 3986). &lt;code&gt;encodeURIComponent()&lt;/code&gt; always outputs &lt;code&gt;%20&lt;/code&gt;, which is safe everywhere. If your server expects &lt;code&gt;+&lt;/code&gt;, use &lt;code&gt;%20&lt;/code&gt; anyway — most modern frameworks handle both.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Quick Fix
&lt;/h2&gt;

&lt;p&gt;Next time a URL misbehaves, paste it into a decoder, inspect what is actually being sent, and fix the encoding at the source. A free tool like &lt;a href="https://codetoolbox.pro/tools/url-encoder.html" rel="noopener noreferrer"&gt;CodeToolbox URL Encoder&lt;/a&gt; does this in your browser — no server uploads, instant results.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Base64 Decoded: What Actually Happens When You Hit 'Encode'</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Sun, 26 Jul 2026 13:06:07 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/base64-decoded-what-actually-happens-when-you-hit-encode-1h06</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/base64-decoded-what-actually-happens-when-you-hit-encode-1h06</guid>
      <description>&lt;p&gt;Base64 is not encryption — it's encoding. If you paste &lt;code&gt;Hello&lt;/code&gt; into a Base64 encoder and get &lt;code&gt;SGVsbG8=&lt;/code&gt;, no secret key was used. The algorithm just translates binary data into 64 printable ASCII characters so it can travel through text-only channels like email, JSON, and URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Algorithm in Plain English
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Take your input bytes and group them in sets of 3 (24 bits total).&lt;/li&gt;
&lt;li&gt;Split those 24 bits into four 6-bit chunks.&lt;/li&gt;
&lt;li&gt;Each 6-bit value (0-63) maps to one character in the Base64 alphabet: &lt;code&gt;A-Z&lt;/code&gt;, &lt;code&gt;a-z&lt;/code&gt;, &lt;code&gt;0-9&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the input isn't a multiple of 3 bytes, add &lt;code&gt;=&lt;/code&gt; padding to round it out.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For &lt;code&gt;Hello&lt;/code&gt; (5 bytes), the encoder processes bytes 0-2 as one group (producing 4 characters), then bytes 3-4 as a 2-byte group (producing 3 characters + 1 &lt;code&gt;=&lt;/code&gt;). Result: 8 characters — &lt;code&gt;SGVsbG8=&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where You Encounter Base64 Every Day
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data URIs&lt;/strong&gt; — embed images directly in HTML/CSS as &lt;code&gt;data:image/png;base64,iVBOR...&lt;/code&gt;, saving HTTP requests for small icons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT tokens&lt;/strong&gt; — the payload section of every JSON Web Token is Base64-encoded JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email attachments&lt;/strong&gt; — MIME uses Base64 to send binary files through text-only SMTP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API authentication&lt;/strong&gt; — Basic Auth encodes &lt;code&gt;username:password&lt;/code&gt; as a Base64 string in the &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline SVGs&lt;/strong&gt; — embed vector graphics in a single HTML file without external dependencies.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Standard vs URL-safe.&lt;/strong&gt; Standard Base64 uses &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt;, which break in URLs. URL-safe Base64 replaces them with &lt;code&gt;-&lt;/code&gt; and &lt;code&gt;_&lt;/code&gt; and strips the &lt;code&gt;=&lt;/code&gt; padding. If you are encoding something for a query string, always use the URL-safe variant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Base64 expands data by ~33%.&lt;/strong&gt; Encoding 1 MB of binary produces ~1.33 MB of text. For large payloads, gzip the original data &lt;em&gt;before&lt;/em&gt; Base64-encoding to offset the bloat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is not encryption.&lt;/strong&gt; Anyone can decode Base64 with zero effort. Never use it as a security measure — it provides exactly zero confidentiality.&lt;/p&gt;




&lt;p&gt;Try it yourself: &lt;a href="https://codetoolbox.pro/tools/base64.html" rel="noopener noreferrer"&gt;Base64 Encoder/Decoder&lt;/a&gt; — free, no signup, works entirely in your browser with no server uploads.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Cron Jobs in 2026: Docker, CI/CD, and Why Your Old crontab Tricks Still Work</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Fri, 24 Jul 2026 13:06:59 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/cron-jobs-in-2026-docker-cicd-and-why-your-old-crontab-tricks-still-work-1mnn</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/cron-jobs-in-2026-docker-cicd-and-why-your-old-crontab-tricks-still-work-1mnn</guid>
      <description>&lt;p&gt;Cron has been scheduling Unix jobs since the 1970s, and it is not going anywhere. But the way we run cron jobs has shifted: from bare-metal servers to Docker containers, from crontab files to CI/CD YAML, and from cron.d to Kubernetes CronJobs. Here is what changed — and what has not.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Cron Inside Docker
&lt;/h2&gt;

&lt;p&gt;Docker containers prefer a single foreground process, so running a cron daemon inside a container feels unnatural. Three modern approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Host cron + &lt;code&gt;docker exec&lt;/code&gt;&lt;/strong&gt;: Run cron on the host, and have each entry invoke &lt;code&gt;docker exec container command&lt;/code&gt;. Zero container changes, works today.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;supercronic&lt;/strong&gt;: A drop-in crontab-compatible runner that logs to stdout/stderr. Perfect for containers whose log drivers expect stdout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ofelia&lt;/strong&gt;: A Docker-native scheduler that reads job config from container labels instead of a crontab file.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. CI/CD Cron: GitHub Actions &amp;amp; Friends
&lt;/h2&gt;

&lt;p&gt;GitHub Actions, GitLab CI, and Jenkins all support cron-triggered pipelines. The syntax is identical to standard 5-field cron:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GitHub Actions — runs every weekday at 9 AM UTC&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;9&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1-5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key difference: CI/CD schedulers use &lt;strong&gt;UTC&lt;/strong&gt; by default, not your local timezone. A &lt;code&gt;0 0 * * *&lt;/code&gt; job that reads "midnight" actually fires at midnight UTC — which may be 8 PM your time. Always verify the timezone offset.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Classic Traps Have Not Changed
&lt;/h2&gt;

&lt;p&gt;Some mistakes transcend the platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Weekday numbering&lt;/strong&gt;: &lt;code&gt;0&lt;/code&gt; is Sunday (POSIX), but Quartz Scheduler and some libraries start at &lt;code&gt;1&lt;/code&gt; for Sunday. Check your platform convention.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OR logic&lt;/strong&gt;: When both day-of-month AND day-of-week are set, the job fires when EITHER matches — not both. This catches everyone at least once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal environment&lt;/strong&gt;: Cron runs without your shell PATH, aliases, or environment variables. Use absolute paths and set &lt;code&gt;SHELL=/bin/bash&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Quick tip&lt;/strong&gt;: I use a &lt;a href="https://codetoolbox.pro/tools/cron-generator.html" rel="noopener noreferrer"&gt;free visual cron generator&lt;/a&gt; to build expressions, see human-readable descriptions, and preview the next 5 execution times before pasting into production. Beats memorizing field order at 2 AM.&lt;/p&gt;

&lt;p&gt;What is the worst cron bug you have deployed? Mine was a timezone mismatch that sent customer emails at 3 AM local time instead of 9 AM.&lt;/p&gt;

</description>
      <category>cron</category>
      <category>devops</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>3 Regex Patterns That Save Hours of Debugging</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Tue, 21 Jul 2026 13:06:26 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/3-regex-patterns-that-save-hours-of-debugging-1o8h</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/3-regex-patterns-that-save-hours-of-debugging-1o8h</guid>
      <description>&lt;p&gt;Every developer has been there: staring at a regex that &lt;em&gt;should&lt;/em&gt; work but doesn't. Here are three patterns I debugged this month that turned hours of head-scratching into one-line fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Non-Greedy Matching (&lt;code&gt;.*?&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;The classic mistake: matching everything between two delimiters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Wrong — grabs everything from first &amp;lt;div&amp;gt; to the LAST &amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;.*&amp;lt;/div&amp;gt;

# Right — stops at the first &amp;lt;/div&amp;gt;
&amp;lt;div&amp;gt;.*?&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;?&lt;/code&gt; after &lt;code&gt;*&lt;/code&gt; makes the quantifier "lazy" — it matches as little as possible instead of as much as possible. This single character fixes more regex bugs than anything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Lookaheads Without Lookbehinds
&lt;/h2&gt;

&lt;p&gt;Need to match something only when followed by something else? That's a lookahead. Need the opposite? Lookbehinds aren't supported everywhere.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Match "USD" only when followed by a number
USD(?=\d+)

# Match a number only when preceded by "$"
(?&amp;lt;=\$)\d+\.?\d*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lookaheads work in every browser and language. Lookbehinds fail silently in Safari. When in doubt, capture instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Capture Groups vs. Non-Capturing
&lt;/h2&gt;

&lt;p&gt;Every &lt;code&gt;(...)&lt;/code&gt; creates a capture group. If you're grouping for precedence (not extraction), use &lt;code&gt;(?:...)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Creates 2 unnecessary capture groups
(https?|ftp)://(www\.)?(example\.com)

# Cleaner — only captures what matters
(?:https?|ftp)://(?:www\.)?(example\.com)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you're writing a replacement with &lt;code&gt;$5&lt;/code&gt; and &lt;code&gt;$7&lt;/code&gt;, you'll thank yourself for keeping the group count low.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Quick test tip:&lt;/strong&gt; When debugging regex, I use a &lt;a href="https://codetoolbox.pro/tools/regex-tester.html" rel="noopener noreferrer"&gt;free online regex tester&lt;/a&gt; that shows match highlighting and capture groups in real time. Paste your pattern, write test cases, iterate — all in the browser.&lt;/p&gt;

&lt;p&gt;What's the worst regex bug you've shipped? Drop it in the comments — I'll go first: I once used &lt;code&gt;[0-9]&lt;/code&gt; instead of &lt;code&gt;[0-9]+&lt;/code&gt; in a credit card validator…&lt;/p&gt;

</description>
      <category>regex</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Stop Using 'password123': A Developer's Guide to Strong Passwords</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Sun, 19 Jul 2026 13:05:44 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/stop-using-password123-a-developers-guide-to-strong-passwords-1on1</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/stop-using-password123-a-developers-guide-to-strong-passwords-1on1</guid>
      <description>&lt;p&gt;Every developer knows the drill: create an account, type a "temporary" password, and promise to change it later. Months go by, and that password — often something painfully predictable — is still protecting your production database, your CI/CD pipeline, or your cloud console.&lt;/p&gt;

&lt;p&gt;Let's fix that. Here's what actually makes a password strong, and how to generate one you can trust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Length Is Everything
&lt;/h2&gt;

&lt;p&gt;People obsess over adding symbols and uppercase letters, but length is the single biggest factor in password strength. A 16-character all-lowercase password takes centuries to brute-force with today's hardware. An 8-character password with symbols takes hours.&lt;/p&gt;

&lt;p&gt;Every additional character multiplies the search space exponentially. A 12-character password using only lowercase letters has 26¹² ≈ 95 quadrillion combinations. Add just 4 more characters, and you jump to 26¹⁶ ≈ 43 sextillion. That's the difference between crackable and effectively uncrackable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Randomness &amp;gt; Cleverness
&lt;/h2&gt;

&lt;p&gt;Your brain is terrible at randomness. "CorrectHorseBatteryStaple" is predictable because it uses dictionary words. "P@ssw0rd!" is in every rainbow table ever compiled. The only reliable way to generate a truly strong password is to let a cryptographically secure random number generator do it.&lt;/p&gt;

&lt;p&gt;In the browser, that means &lt;code&gt;crypto.getRandomValues()&lt;/code&gt; — the Web Crypto API backed by your OS's entropy source. It's the same API that password managers like 1Password and Bitwarden use under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking Your Password's Strength
&lt;/h2&gt;

&lt;p&gt;Not all "strong" passwords are equal. A good password generator should show a strength indicator based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Length&lt;/strong&gt; (the biggest factor — aim for 16+)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Character variety&lt;/strong&gt; (lowercase + uppercase + numbers + symbols = 4 character pools)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;True randomness&lt;/strong&gt; (no human-chosen patterns)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use a &lt;a href="https://codetoolbox.pro/tools/password-generator.html" rel="noopener noreferrer"&gt;free password generator&lt;/a&gt; that shows real-time strength feedback and lets you customize length and charsets. Everything runs locally via &lt;code&gt;crypto.getRandomValues()&lt;/code&gt; — the generated password never touches a server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Tips for Developers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API keys/tokens&lt;/strong&gt;: use 32-64 character alphanumeric strings (no symbols — some systems choke on special chars)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database passwords&lt;/strong&gt;: 20+ characters, all four charsets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wi-Fi passwords&lt;/strong&gt;: 20+ characters — they're shared, so make them strong enough to survive a handoff&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never reuse&lt;/strong&gt;: a strong password used on two sites is a weak password&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Stop typing "Summer2026!" and convincing yourself it's fine. Use a generator, pick 16+ characters, and let entropy do the work. Your production environment will thank you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's the worst password you've seen in a codebase? (Config files committed to public repos, I'm looking at you.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>5 Signs Your Regex Is Wrong (and How to Spot Them in Seconds)</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Thu, 16 Jul 2026 13:05:52 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/5-signs-your-regex-is-wrong-and-how-to-spot-them-in-seconds-13ba</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/5-signs-your-regex-is-wrong-and-how-to-spot-them-in-seconds-13ba</guid>
      <description>&lt;p&gt;We've all been there. You write a regex, it looks correct, you deploy it... and then the bug reports roll in. Regex is deceptively tricky — what looks right often contains subtle flaws that only surface with specific inputs. Here are five telltale signs your pattern needs fixing, and how to catch them before they hit production.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. It Matches Way More Than You Expected
&lt;/h2&gt;

&lt;p&gt;This is the #1 regex gotcha. You write &lt;code&gt;&amp;lt;.*&amp;gt;&lt;/code&gt; to match HTML tags, but it swallows the entire &lt;code&gt;&amp;lt;div&amp;gt;hello&amp;lt;/div&amp;gt;&amp;lt;span&amp;gt;world&amp;lt;/span&amp;gt;&lt;/code&gt; in one match. The culprit? &lt;strong&gt;Greedy quantifiers.&lt;/strong&gt; By default, &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;+&lt;/code&gt; match as much as possible. Add &lt;code&gt;?&lt;/code&gt; after the quantifier to make it lazy: &lt;code&gt;&amp;lt;.*?&amp;gt;&lt;/code&gt; matches each tag individually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spot it:&lt;/strong&gt; A visual regex tester with match highlighting makes this instantly obvious — when one match spans three lines of text, you know something's off.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. It Silently Returns Zero Matches
&lt;/h2&gt;

&lt;p&gt;No errors, no warnings — just zero results. This usually means your anchors (&lt;code&gt;^&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;) are in the wrong place, or you forgot that &lt;code&gt;.&lt;/code&gt; doesn't match newlines by default. Toggle the multiline (&lt;code&gt;m&lt;/code&gt;) flag and watch the behavior change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spot it:&lt;/strong&gt; If you're staring at a blank results pane, check your anchors and flags before rewriting the pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Capture Groups Return Empty or Wrong Values
&lt;/h2&gt;

&lt;p&gt;You wrapped a subpattern in parentheses, but the captured value is empty or contains the wrong text. This happens when nested groups interfere with each other, or a quantifier makes the group optional. Reorder your groups from most-specific to least-specific, and use non-capturing groups &lt;code&gt;(?:...)&lt;/code&gt; for grouping without capturing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spot it:&lt;/strong&gt; A tester that shows individual capture group values per match (not just the full match) lets you verify each extraction without console.log debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. It "Works" But Fails on Edge Cases
&lt;/h2&gt;

&lt;p&gt;Your email regex &lt;code&gt;\w+@\w+\.\w+&lt;/code&gt; passes your test, but fails on &lt;code&gt;user.name+tag@domain.co.uk&lt;/code&gt;. The pattern was too simplistic — real-world input is messier than your test data. Throw unicode, special characters, empty strings, and deliberately malformed input at your pattern before shipping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spot it:&lt;/strong&gt; Paste 5-10 edge-case strings into the test area and watch the highlighting. If any legitimate input doesn't highlight, your pattern needs hardening.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The RegExp Constructor Throws a Syntax Error
&lt;/h2&gt;

&lt;p&gt;Unbalanced brackets, missing escapes, or invalid lookbehind syntax crash the &lt;code&gt;new RegExp()&lt;/code&gt; call. In production, this throws an unhandled error. In development, you catch it — but only if you test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spot it:&lt;/strong&gt; A good tester surfaces syntax errors immediately as you type, with a clear error message pointing to the problem character. No need to open the browser console.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Visual Debugging Beats Mental Parsing
&lt;/h2&gt;

&lt;p&gt;The fastest way to debug regex isn't staring at the pattern harder — it's testing it visually. I use a &lt;a href="https://codetoolbox.pro/tools/regex-tester.html" rel="noopener noreferrer"&gt;free online regex tester&lt;/a&gt; that highlights matches in real-time, shows capture group breakdowns, and comes with presets for common patterns (email, URL, IPv4, dates). Every keystroke gives instant feedback — no compile-run-debug cycle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick workflow:&lt;/strong&gt; Paste your regex → toggle flags → paste test data → watch matches highlight → refine until correct → copy the final pattern into your code.&lt;/p&gt;

&lt;p&gt;All processing runs locally in your browser, so you can safely test with real data without uploading anything to a server.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's your go-to regex debugging technique? Have you been bitten by a subtle regex bug that took hours to find? Drop your war stories in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>regex</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Stop Uploading Your Images to Random Servers: Compress Locally Instead</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Tue, 14 Jul 2026 13:06:28 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/stop-uploading-your-images-to-random-servers-compress-locally-instead-2053</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/stop-uploading-your-images-to-random-servers-compress-locally-instead-2053</guid>
      <description>&lt;p&gt;Every time you use a "free online image compressor," ask yourself: &lt;strong&gt;where is my image being sent?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most image compression tools upload your files to a remote server for processing. Your photos, screenshots, and design assets pass through someone else's infrastructure — and there's no way to know if they're stored, scanned, or resold.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local Compression Is Not Magic — It's Canvas
&lt;/h2&gt;

&lt;p&gt;The HTML5 Canvas API has had everything we need for client-side image compression for years. Here's the core idea:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load the image into the browser&lt;/li&gt;
&lt;li&gt;Draw it onto an invisible canvas&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;toBlob()&lt;/code&gt; with your quality setting&lt;/li&gt;
&lt;li&gt;Download the result&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Zero bytes leave your computer. The entire pipeline runs on your hardware, and it's surprisingly fast — milliseconds for most images.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 Things I Learned Compressing Hundreds of Images
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. WebP Is the Undisputed King
&lt;/h3&gt;

&lt;p&gt;Switching your output format from JPEG to WebP typically saves &lt;strong&gt;25-35% more space&lt;/strong&gt; at the same visual quality. Every modern browser supports it. Unless you need IE11 compatibility (and I hope you don't), WebP is a no-brainer.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Resizing Before Compressing Doubles the Savings
&lt;/h3&gt;

&lt;p&gt;If your original photo is 4000×3000 but your website only displays it at 800px wide: resize first, compress second. That 5MB photo can drop below 50KB with both steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Visual Breakpoint Technique
&lt;/h3&gt;

&lt;p&gt;Start at 100% quality and slide down while watching the preview side-by-side. The moment you spot degradation, bump back up 5%. That's your sweet spot — maximum compression with zero visible difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tool I Actually Use
&lt;/h2&gt;

&lt;p&gt;I've been using the &lt;a href="https://codetoolbox.pro/tools/image-compressor.html" rel="noopener noreferrer"&gt;CodeToolbox Image Compressor&lt;/a&gt; — it runs entirely in the browser, no uploads, no signup, no daily limits. Drop an image, tweak the slider, see the side-by-side preview, and download. &lt;/p&gt;

&lt;p&gt;It handles JPEG, PNG, and WebP conversion in both directions. The offline support is a nice bonus: once the page loads, it works on planes and metered connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;p&gt;Local image compression isn't some exotic feature — it's table stakes in 2026. If a tool needs to upload your files to a server to resize them, find a better tool. Your users' privacy (and your page load times) will thank you.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>performance</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Why UUIDs Belong in Every Developer's Toolbelt (Not Just Your Database)</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Sat, 11 Jul 2026 13:04:51 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/why-uuids-belong-in-every-developers-toolbelt-not-just-your-database-4jdd</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/why-uuids-belong-in-every-developers-toolbelt-not-just-your-database-4jdd</guid>
      <description>&lt;p&gt;Most developers first encounter UUIDs when setting up database primary keys. But UUIDs solve problems far beyond the database — and once you start using them, you'll wonder why you ever reached for auto-increment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Sequential IDs
&lt;/h2&gt;

&lt;p&gt;Auto-increment IDs are fast and small, but they leak information. Every &lt;code&gt;/users/42&lt;/code&gt; tells an attacker there are at least 42 users. Every &lt;code&gt;/orders/1087&lt;/code&gt; reveals your order volume. In a REST API, sequential IDs are an enumeration attack waiting to happen.&lt;/p&gt;

&lt;p&gt;UUIDs fix this by being unguessable. &lt;code&gt;/users/550e8400-e29b-41d4-a716-446655440000&lt;/code&gt; tells an attacker nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the Database: Where UUIDs Shine
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Idempotency Keys.&lt;/strong&gt; When processing payments or API calls, the client generates a UUID as an idempotency key before sending the request. If the network drops and the client retries, the server recognizes the same key and avoids double-charging. Stripe's API requires this pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optimistic UI.&lt;/strong&gt; In collaborative apps like Figma or Notion, the client generates UUIDs for new elements before the server confirms. This gives instant feedback — no waiting for a database round-trip to get an ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File Uploads.&lt;/strong&gt; Use UUIDs for uploaded filenames instead of the user's original filename. &lt;code&gt;/uploads/550e8400-e29b-41d4-a716-446655440000.pdf&lt;/code&gt; avoids naming conflicts and doesn't leak the original filename.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed Systems.&lt;/strong&gt; When multiple services generate IDs independently, auto-increment fails — they'd collide. UUIDs let every service create IDs without coordination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating UUIDs in Your Stack
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Browser &amp;amp; Node.js 19+&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; "550e8400-e29b-41d4-a716-446655440000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;uuid&lt;/span&gt;
&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Are They Too Big?
&lt;/h2&gt;

&lt;p&gt;A UUID is 16 bytes as binary, or 36 characters as a string. For modern databases like PostgreSQL (which has a native &lt;code&gt;uuid&lt;/code&gt; type storing only 16 bytes), the overhead is negligible. For MySQL, store UUIDs as &lt;code&gt;BINARY(16)&lt;/code&gt; instead of &lt;code&gt;CHAR(36)&lt;/code&gt; to save space.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;UUIDs aren't just for databases. They're for idempotent APIs, offline-first apps, file storage, and any system where multiple pieces need to generate IDs without talking to each other. If you need to quickly generate UUIDs for testing or development, I keep &lt;a href="https://codetoolbox.pro/tools/uuid-generator.html" rel="noopener noreferrer"&gt;this free UUID generator&lt;/a&gt; bookmarked — it supports bulk generation up to 100 at a time, and all processing happens locally in your browser.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>5 Markdown Tricks That Make Your README Stand Out</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Thu, 09 Jul 2026 13:06:25 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/5-markdown-tricks-that-make-your-readme-stand-out-dmm</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/5-markdown-tricks-that-make-your-readme-stand-out-dmm</guid>
      <description>&lt;p&gt;I've reviewed hundreds of GitHub READMEs while contributing to open source, and the difference between a forgettable one and one that makes people stop scrolling often comes down to a few small Markdown tricks.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Collapsible Sections for Long Content
&lt;/h2&gt;

&lt;p&gt;Nobody wants to scroll through 2,000 lines of setup instructions. Use HTML &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; tags to hide secondary content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;details&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;Advanced Configuration&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;

Your long config docs here...

&lt;span class="nt"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This renders as a clickable expandable section that keeps your README scannable.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Task Lists for Roadmaps
&lt;/h2&gt;

&lt;p&gt;GFM task lists aren't just for personal to-dos. Use them as a public roadmap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; [x] Core API (v1.0)
&lt;span class="p"&gt;-&lt;/span&gt; [x] Webhook support
&lt;span class="p"&gt;-&lt;/span&gt; [ ] GraphQL endpoint
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Multi-region deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users instantly see what's done and what's coming.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Reference-Style Links for Cleaner Source
&lt;/h2&gt;

&lt;p&gt;Inline links make raw Markdown hard to read. Reference-style links keep paragraphs clean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Check the &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;contributing guide&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;contrib&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; for details.

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;contrib&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="sx"&gt;CONTRIBUTING.md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Mermaid Diagrams Inside Code Blocks
&lt;/h2&gt;

&lt;p&gt;GitHub renders Mermaid diagrams in fenced code blocks. Show architecture without uploading an image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;mermaid
&lt;/span&gt;&lt;span class="sb"&gt;graph LR
    Client--&amp;gt;API--&amp;gt;Database
    API--&amp;gt;Cache&lt;/span&gt;
&lt;span class="p"&gt;```&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Align Tables with Consistent Column Widths
&lt;/h2&gt;

&lt;p&gt;Tables are Markdown's weakest feature. Make them maintainable by aligning columns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| Parameter | Type   | Default | Description        |
|-----------|--------|---------|--------------------|
| timeout   | number | 5000    | Request timeout ms |
| retries   | number | 3       | Max retry attempts |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding spaces so the pipes align makes the raw source readable.&lt;/p&gt;




&lt;p&gt;The fastest way to test any of these is a live preview. I use &lt;a href="https://codetoolbox.pro/tools/markdown-preview.html" rel="noopener noreferrer"&gt;this free Markdown previewer&lt;/a&gt; when drafting READMEs or blog posts — it renders GFM tables, task lists, and diagrams in real time without touching a server.&lt;/p&gt;

</description>
      <category>markdown</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>3 Times You Need Base64 (and One Time You Definitely Don't)</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Wed, 01 Jul 2026 01:40:20 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/3-times-you-need-base64-and-one-time-you-definitely-dont-317</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/3-times-you-need-base64-and-one-time-you-definitely-dont-317</guid>
      <description>&lt;h2&gt;
  
  
  When Base64 Makes Sense
&lt;/h2&gt;

&lt;p&gt;Base64 converts binary data into text using 64 printable ASCII characters so it can travel through systems that don't handle raw bytes well. Here are three times you actually need it, and one time you shouldn't bother.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Embedding Small Images in HTML/CSS
&lt;/h3&gt;

&lt;p&gt;Inline images via data URIs eliminate HTTP requests. For tiny assets like icons and email signature graphics, this is genuinely faster than a separate file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"data:image/png;base64,iVBORw0KGgo..."&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tradeoff: Base64 inflates file size by ~33%. For anything over 5KB, a separate file with browser caching wins. But for that one-off SVG favicon or email footer, inline Base64 is perfect.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Sending Binary in JSON APIs
&lt;/h3&gt;

&lt;p&gt;JSON can't carry raw bytes. When your API needs file uploads alongside metadata, Base64-encoding is the standard approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"filename"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"report.pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JVBERi0xLjQKJeLjz9MK..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most cloud APIs (AWS Lambda payloads, webhook implementations) use this pattern under the hood.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Debugging Tokens and Auth Headers
&lt;/h3&gt;

&lt;p&gt;JWT payloads are just Base64URL. Basic Auth headers are Base64-encoded user:pass. When debugging, paste a JWT's middle segment into any Base64 decoder and read the claims directly. Same trick for Authorization: Basic *** headers — decode the token after "Basic " to see the credentials.&lt;/p&gt;

&lt;h3&gt;
  
  
  When NOT to Use Base64
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;For security.&lt;/strong&gt; Base64 is encoding, not encryption. It's trivially reversible and offers zero protection. I've seen devs Base64-encode API keys in client-side code thinking it hides them. It doesn't. Use AES-256 for actual security.&lt;/p&gt;




&lt;p&gt;Need a quick Base64 encoder/decoder? I use &lt;a href="https://codetoolbox.pro/tools/base64.html" rel="noopener noreferrer"&gt;this free tool&lt;/a&gt; — it runs entirely in the browser, handles files and data URIs, and works with both standard and URL-safe variants.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>security</category>
    </item>
    <item>
      <title>Your JSON Is Valid... Until It's Not: Common Parse Errors and How to Fix Them</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Wed, 24 Jun 2026 13:02:56 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/your-json-is-valid-until-its-not-common-parse-errors-and-how-to-fix-them-3epg</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/your-json-is-valid-until-its-not-common-parse-errors-and-how-to-fix-them-3epg</guid>
      <description>&lt;p&gt;We've all seen it: an API response that looks perfectly fine, but &lt;code&gt;JSON.parse()&lt;/code&gt; throws a cryptic error at position 0. Or position 472. Or somewhere deep inside a 10,000-line config file. Here are the most common JSON syntax issues and how to diagnose them fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Trailing Commas (The #1 Offender)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"lodash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JSON spec (RFC 8259) &lt;strong&gt;does not allow trailing commas&lt;/strong&gt;. JavaScript and TypeScript are forgiving, so your IDE doesn't complain — but strict JSON parsers will fail. The fix: remove the comma after the last array item and last object key.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Smart Quotes vs. Straight Quotes
&lt;/h2&gt;

&lt;p&gt;If you copy JSON from a word processor or a ChatGPT output, you might get "smart quotes" (curly) instead of straight quotes. They look similar but are different Unicode characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;WILL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;fail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;smart&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;quotes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;key&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;“name”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“hello”&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;This&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;correct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Unquoted Keys
&lt;/h2&gt;

&lt;p&gt;JavaScript objects let you use unquoted keys. JSON does not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Valid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;JS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;object,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;INVALID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;JSON&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;age:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Correct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;JSON&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. The Invisible BOM
&lt;/h2&gt;

&lt;p&gt;If your JSON file starts with a UTF-8 BOM (Byte Order Mark), many parsers fail at position 0 — even though the file looks empty of problems. &lt;code&gt;cat file.json | xxd | head -1&lt;/code&gt; and look for &lt;code&gt;EF BB BF&lt;/code&gt; at the start.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Single Quotes
&lt;/h2&gt;

&lt;p&gt;JavaScript accepts both single and double quotes for strings. JSON does not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Invalid&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;'key':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Valid&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Debugging Tip
&lt;/h2&gt;

&lt;p&gt;When you encounter a parse error, don't just stare at the JSON. Use a formatter that shows the exact line and column of the first syntax error.&lt;/p&gt;

&lt;p&gt;I built a &lt;strong&gt;&lt;a href="https://codetoolbox.pro/tools/json-formatter.html" rel="noopener noreferrer"&gt;free JSON formatter and validator&lt;/a&gt;&lt;/strong&gt; for exactly this purpose — paste your JSON, click Validate, and it tells you &lt;em&gt;exactly&lt;/em&gt; where the error is. All processing happens in your browser, no data leaves your machine.&lt;/p&gt;

&lt;p&gt;The most useful feature: it works offline once the page loads. I've used it on flights to debug local config files without internet.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Got a favorite JSON debugging technique? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>json</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Stop Copy-Pasting Regex You Don't Understand: 5 Patterns Explained</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Sun, 21 Jun 2026 13:05:23 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/stop-copy-pasting-regex-you-dont-understand-5-patterns-explained-335a</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/stop-copy-pasting-regex-you-dont-understand-5-patterns-explained-335a</guid>
      <description>&lt;h2&gt;
  
  
  Stop Copy-Pasting Regex You Don't Understand: 5 Patterns Explained
&lt;/h2&gt;

&lt;p&gt;Every developer has done it: you Google "regex for email," copy the first Stack Overflow answer, paste it into your code, and cross your fingers that it covers all edge cases. Then six months later, &lt;code&gt;user+tag@domain.co.uk&lt;/code&gt; slips through and breaks something.&lt;/p&gt;

&lt;p&gt;Let's fix that. Here are five regex patterns you probably copy-paste, explained so you actually understand them — and can adapt them yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Email Validation: The Pattern Everyone Gets Wrong
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Broken down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[a-zA-Z0-9._%+-]+&lt;/code&gt; — username part: letters, digits, dots, underscores, percent, plus, hyphens. The &lt;code&gt;+&lt;/code&gt; means "one or more."&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@&lt;/code&gt; — literal at sign.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[a-zA-Z0-9.-]+&lt;/code&gt; — domain name: letters, digits, dots, hyphens.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\.&lt;/code&gt; — literal dot (escaped because &lt;code&gt;.&lt;/code&gt; normally means "any character").&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[a-zA-Z]{2,}&lt;/code&gt; — TLD: at least 2 letters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When it fails:&lt;/strong&gt; Unicode characters in the local part (&lt;code&gt;café@example.com&lt;/code&gt;), quoted strings, IP-address domains. For production email validation, send a confirmation link — regex alone can't guarantee deliverability.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. URL Extraction: Greedy vs. Lazy Trap
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https?:\/\/[^\s/$.?#].[^\s]*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;https?&lt;/code&gt; — "http" optionally followed by "s." The &lt;code&gt;?&lt;/code&gt; makes the preceding character optional.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:\/\/&lt;/code&gt; — literal &lt;code&gt;://&lt;/code&gt; (forward slashes must be escaped outside character classes).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[^\s/$.?#]&lt;/code&gt; — match one character that is NOT whitespace, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;.&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, or &lt;code&gt;#&lt;/code&gt;. This prevents matching bare punctuation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[^\s]*&lt;/code&gt; — then match everything until whitespace (&lt;code&gt;\s&lt;/code&gt;). Note the &lt;code&gt;*&lt;/code&gt; (zero or more) — if the URL is followed by a space, it stops there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pitfall:&lt;/strong&gt; The &lt;code&gt;*&lt;/code&gt; after &lt;code&gt;[^\s]&lt;/code&gt; is greedy — always use it with a character class (&lt;code&gt;[^\s]&lt;/code&gt;) rather than &lt;code&gt;.&lt;/code&gt; to avoid gobbling up surrounding text. Test this in the regex tester with URLs embedded in paragraphs to see the difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. IP Address Extraction: Backreference Magic
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\b(?:\d{1,3}\.){3}\d{1,3}\b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;\b&lt;/code&gt; — word boundary: ensures we don't match "192.168.1.1" inside "192.168.1.100".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(?:\d{1,3}\.)&lt;/code&gt; — a non-capturing group (&lt;code&gt;?:&lt;/code&gt;): one to three digits followed by a dot. Non-capturing groups group without saving the match.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{3}&lt;/code&gt; — repeat the group exactly 3 times. So we get &lt;code&gt;123.45.67.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\d{1,3}&lt;/code&gt; — final octet, no trailing dot.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\b&lt;/code&gt; — word boundary again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This pattern doesn't validate IPs&lt;/strong&gt; — it matches &lt;code&gt;999.999.999.999&lt;/code&gt;. For validation, you'd need a much more complex pattern checking each octet's range (0-255). This pattern's job is extraction, not validation — it finds anything that looks like an IP in a log file.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Date Extraction (ISO 8601): Character Classes Done Right
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;\d{4}&lt;/code&gt; — exactly 4 digits (the year).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-&lt;/code&gt; — literal hyphen.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(0[1-9]|1[0-2])&lt;/code&gt; — month: either &lt;code&gt;0&lt;/code&gt; followed by 1-9 (Jan-Sep) OR &lt;code&gt;1&lt;/code&gt; followed by 0-2 (Oct-Dec). The &lt;code&gt;|&lt;/code&gt; means "OR."&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-&lt;/code&gt; — literal hyphen.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(0[1-9]|[12]\d|3[01])&lt;/code&gt; — day: &lt;code&gt;0[1-9]&lt;/code&gt; (1st-9th) OR &lt;code&gt;[12]\d&lt;/code&gt; (10-29) OR &lt;code&gt;3[01]&lt;/code&gt; (30-31).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Known limitation:&lt;/strong&gt; This accepts invalid dates like &lt;code&gt;2025-02-30&lt;/code&gt;. For bulletproof date validation, parse with a date library after the regex confirms the format.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The "Everything Between Tags" Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;([a-zA-Z][a-zA-Z0-9]*)&amp;gt;(.*?)&amp;lt;\/\1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;([a-zA-Z][a-zA-Z0-9]*)&amp;gt;&lt;/code&gt; — opening tag: &lt;code&gt;&amp;lt;&lt;/code&gt;, a letter, then optional alphanumeric characters, &lt;code&gt;&amp;gt;&lt;/code&gt;. The parentheses capture the tag name.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(.*?)&lt;/code&gt; — content between tags. The &lt;code&gt;?&lt;/code&gt; after &lt;code&gt;*&lt;/code&gt; makes it &lt;strong&gt;lazy&lt;/strong&gt; — stop at the first closing tag, not the last.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;\/\1&amp;gt;&lt;/code&gt; — closing tag: &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, then &lt;code&gt;&lt;/code&gt; (backreference to the first capture group, the tag name), &lt;code&gt;&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without the lazy &lt;code&gt;*?&lt;/code&gt;, &lt;code&gt;&amp;lt;.*&amp;gt;&lt;/code&gt; applied to &lt;code&gt;&amp;lt;div&amp;gt;hello&amp;lt;/div&amp;gt;&lt;/code&gt; would match the entire string instead of just &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;. This is the #1 "why isn't my regex working" moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Debugging Workflow I Actually Use
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Start with a known-good preset (email, URL, IPv4 from the tool's library)&lt;/li&gt;
&lt;li&gt;Tweak one thing at a time, watching the match highlights change in real-time&lt;/li&gt;
&lt;li&gt;Add edge cases to the test string: empty input, special chars, unicode&lt;/li&gt;
&lt;li&gt;Only move to production code when the tester shows exactly what you expect&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I use the &lt;strong&gt;free Regex Tester&lt;/strong&gt; at &lt;a href="https://codetoolbox.pro/tools/regex-tester.html" rel="noopener noreferrer"&gt;codetoolbox.pro/tools/regex-tester.html&lt;/a&gt; for this — it runs entirely in the browser, highlights matches instantly, and shows capture groups individually. No signup, no server uploads.&lt;/p&gt;




&lt;p&gt;What's the regex that burned you the worst? Drop a comment — genuinely curious how many of us have been bitten by the same patterns.&lt;/p&gt;

</description>
      <category>regex</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
