<?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>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>
    <item>
      <title>Why Your API Calls Break: A Developer's Guide to URL Encoding</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Fri, 19 Jun 2026 13:09:27 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/why-your-api-calls-break-a-developers-guide-to-url-encoding-agj</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/why-your-api-calls-break-a-developers-guide-to-url-encoding-agj</guid>
      <description>&lt;h2&gt;
  
  
  Why Your API Calls Break: A Developer's Guide to URL Encoding
&lt;/h2&gt;

&lt;p&gt;URL encoding is one of those things that seems trivial until it isn't. You fire off an API call, the server returns a 400, and you stare at the URL wondering what went wrong. Nine times out of ten, the answer is encoding.&lt;/p&gt;

&lt;p&gt;Here are the three URL encoding mistakes that cost developers hours of debugging — and how to fix them in 30 seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Double-Encoding Trap
&lt;/h3&gt;

&lt;p&gt;This is the most insidious bug. You encode a URL once, pass it through a framework or middleware that encodes it &lt;em&gt;again&lt;/em&gt;, and suddenly &lt;code&gt;hello%20world&lt;/code&gt; becomes &lt;code&gt;hello%2520world&lt;/code&gt; (the &lt;code&gt;%&lt;/code&gt; got encoded to &lt;code&gt;%25&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The symptom:&lt;/strong&gt; Downstream services receive garbled data. OAuth callback URLs fail silently. API gateways forward corrupted parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Before encoding, decode first to establish a clean baseline:&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="c1"&gt;// Bad: might double-encode&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com?q=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Good: decode first if input might already be encoded&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;decodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// throws if malformed&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com?q=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you suspect double-encoding, look for &lt;code&gt;%25&lt;/code&gt; in your output — that's the smoking gun (&lt;code&gt;%&lt;/code&gt; encoded as &lt;code&gt;%25&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The &lt;code&gt;+&lt;/code&gt; vs &lt;code&gt;%20&lt;/code&gt; Confusion
&lt;/h3&gt;

&lt;p&gt;Both represent a space, but they're NOT interchangeable across contexts.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Encoding&lt;/th&gt;
&lt;th&gt;Works?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Query string (form data)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query string (manual)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%20&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Path segment&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ Broken&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fragment identifier&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ Broken&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Everywhere&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%20&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ Always&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; Use &lt;code&gt;%20&lt;/code&gt; when you're not sure. It works universally. Use &lt;code&gt;+&lt;/code&gt; only for &lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt; form submissions.&lt;/p&gt;

&lt;p&gt;JavaScript's &lt;code&gt;encodeURIComponent()&lt;/code&gt; outputs &lt;code&gt;%20&lt;/code&gt; — the safe choice. Python's &lt;code&gt;urllib.parse.quote()&lt;/code&gt; does the same by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Encoding the Wrong Thing
&lt;/h3&gt;

&lt;p&gt;The most common pattern I see in code reviews:&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="c1"&gt;// Wrong: encodeURI on a full URL&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&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://api.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;// Result: "https://api.example.com/search?q=hello%20world" (works, but fragile)&lt;/span&gt;

&lt;span class="c1"&gt;// Wrong: encodeURIComponent on a full URL&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&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;https://api.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;// Result: "https%3A%2F%2Fapi.example.com%2Fsearch%3Fq%3Dhello%20world" (broken)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The rule:&lt;/strong&gt; &lt;code&gt;encodeURI()&lt;/code&gt; for entire URLs (preserves &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;). &lt;code&gt;encodeURIComponent()&lt;/code&gt; for individual parameter values. Never mix them up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Debugging Workflow
&lt;/h3&gt;

&lt;p&gt;When an API call fails with encoding issues, I use this 3-step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Decode the URL&lt;/strong&gt; to see what's actually there — strip away the percent-encoding and read the raw string&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-encode a clean version&lt;/strong&gt; — start fresh from the decoded text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare&lt;/strong&gt; — if the re-encoded version works but the original doesn't, you had double-encoding or mixed encoding&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I keep a &lt;strong&gt;free URL Encoder/Decoder&lt;/strong&gt; bookmarked for exactly this: paste a broken URL, hit Decode, and instantly see what went wrong. No signup, no server uploads — everything runs in your browser.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://codetoolbox.pro/tools/url-encoder.html" rel="noopener noreferrer"&gt;codetoolbox.pro/tools/url-encoder.html&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern Alternative: URLSearchParams
&lt;/h3&gt;

&lt;p&gt;If you're writing modern JavaScript, the &lt;code&gt;URL&lt;/code&gt; and &lt;code&gt;URLSearchParams&lt;/code&gt; APIs handle encoding automatically:&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;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;q&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="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/search?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// "https://api.example.com/search?q=hello+world&amp;amp;page=1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is cleaner, safer, and immune to double-encoding. Use it for new code.&lt;/p&gt;




&lt;p&gt;What URL encoding bugs have burned you in production? Drop a comment — I'm collecting war stories.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>api</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Your Website Images Are Killing Your SEO — Here's How to Fix It</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Tue, 16 Jun 2026 13:08:02 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/your-website-images-are-killing-your-seo-heres-how-to-fix-it-43ck</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/your-website-images-are-killing-your-seo-heres-how-to-fix-it-43ck</guid>
      <description>&lt;h2&gt;
  
  
  The Hidden Speed Killer on Every Website
&lt;/h2&gt;

&lt;p&gt;If your web pages take more than 2.5 seconds to load, Google's Core Web Vitals are already penalizing your rankings. And here's the uncomfortable truth: &lt;strong&gt;unoptimized images&lt;/strong&gt; are almost always the single biggest culprit.&lt;/p&gt;

&lt;p&gt;A typical web page downloads 1.5–3 MB of data on desktop — and images account for &lt;strong&gt;50–80% of those bytes&lt;/strong&gt;. A single uncompressed hero image at 4000×3000px can weigh 5 MB. Multiply that by a gallery of 10 product photos and you've got 50 MB of images dragging down every visitor's experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix Is Simpler Than You Think
&lt;/h2&gt;

&lt;p&gt;Compressing images before upload can shrink them by &lt;strong&gt;60–85%&lt;/strong&gt; with zero visible quality loss. Here's what actually works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Choose the right format&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JPEG&lt;/strong&gt; for photographs — lossy but tiny&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PNG&lt;/strong&gt; for screenshots, logos, and anything needing transparency — lossless but larger&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebP&lt;/strong&gt; for the best of both worlds — typically 25–34% smaller than JPEG at identical quality, supported everywhere now&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Use the quality sweet spot&lt;/strong&gt;&lt;br&gt;
70–80% is the magic range for web images. Your visitors won't notice the difference on a screen, but your page will load dramatically faster. Reserve 85%+ for photography portfolios; use 60% for thumbnails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Compress locally, not on some server&lt;/strong&gt;&lt;br&gt;
Most "free" online compressors upload your images to remote servers — where they may be stored, analyzed, or resold. Instead, use a browser-based tool that runs &lt;strong&gt;entirely on your device&lt;/strong&gt; using the Canvas API. Nothing transmitted, nothing stored.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Tool That Actually Respects Your Privacy
&lt;/h2&gt;

&lt;p&gt;I've been using this &lt;a href="https://codetoolbox.pro/tools/image-compressor.html" rel="noopener noreferrer"&gt;free image compressor&lt;/a&gt; that processes everything locally in the browser — no uploads, no server, no sign-up. It handles JPEG, PNG, and WebP with a side-by-side preview so you can dial in the quality/compression balance before downloading.&lt;/p&gt;

&lt;p&gt;For a typical 2 MB product photo, I get it down to ~200 KB at WebP/75% quality — that's a &lt;strong&gt;90% reduction&lt;/strong&gt; with no visible difference on screen.&lt;/p&gt;

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

&lt;p&gt;Image optimization isn't optional anymore — it directly impacts your SEO rankings, bounce rates, and conversion metrics. The good news is that fixing it takes about 30 seconds per image with the right tool. Your users (and Google) will thank you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's your go-to image compression workflow? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>performance</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>3 Base64 Tricks Every Developer Should Know</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Sun, 14 Jun 2026 13:02:56 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/3-base64-tricks-every-developer-should-know-25p7</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/3-base64-tricks-every-developer-should-know-25p7</guid>
      <description>&lt;h2&gt;
  
  
  1. Decode JWT Payloads Without a Library
&lt;/h2&gt;

&lt;p&gt;JSON Web Tokens are everywhere in modern APIs, and their payload is just Base64URL-encoded JSON. When debugging auth issues, you don't need to fire up jwt.io — just grab the middle segment (between the two dots), swap &lt;code&gt;-&lt;/code&gt; and &lt;code&gt;_&lt;/code&gt; for &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt;, and decode it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.abc123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That middle part (&lt;code&gt;eyJzdWIiOiIxMjM0NTY3ODkwIn0&lt;/code&gt;) decodes to &lt;code&gt;{"sub":"1234567890"}&lt;/code&gt; — your user ID, expiry, and scopes, all in plain text. No library required.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Peek Inside HTTP Basic Auth Headers
&lt;/h2&gt;

&lt;p&gt;Ever wondered what credentials your HTTP client is &lt;em&gt;actually&lt;/em&gt; sending? The &lt;code&gt;Authorization: Basic dXNlcjpwYXNz&lt;/code&gt; header is just &lt;code&gt;Base64(username:password)&lt;/code&gt;. Copy the token after "Basic " and decode it — you'll instantly see if the right credentials are being transmitted. Super useful when debugging misbehaving API clients or checking whether environment variables are being picked up correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Embed Images Without Extra HTTP Requests
&lt;/h2&gt;

&lt;p&gt;For small icons, logos, or email signatures, encoding to a &lt;code&gt;data:image/png;base64,...&lt;/code&gt; URI lets you embed the image directly in HTML or CSS. No extra HTTP request, no separate file — perfect for single-page demos, HTML email templates, and performance-critical above-the-fold content. Just keep source images under 5KB or the encoded string gets unwieldy.&lt;/p&gt;




&lt;p&gt;These tricks come up often enough that I built a quick &lt;strong&gt;Base64 encoder/decoder&lt;/strong&gt; that handles both standard Base64 and Base64URL, works with files up to 50MB, and processes everything locally in your browser — nothing ever hits a server. No signup, no ads.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://codetoolbox.pro/tools/base64.html" rel="noopener noreferrer"&gt;Try it at codetoolbox.pro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What Base64 tricks do you use regularly? I'd love to hear about them in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>3 JSON Formatting Tricks That Save Me Hours Every Week</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Thu, 11 Jun 2026 13:08:31 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/3-json-formatting-tricks-that-save-me-hours-every-week-2en1</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/3-json-formatting-tricks-that-save-me-hours-every-week-2en1</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;You're debugging an API response, and it looks like this:&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="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:[{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&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="s2"&gt;"Widget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2024-01-15T08:30:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="s2"&gt;"electronics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"sale"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nl"&gt;"pricing"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;29.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"eur"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26.50&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="nl"&gt;"stock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;},{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&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="s2"&gt;"Gadget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"created"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2024-02-20T14:15:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="s2"&gt;"office"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="nl"&gt;"pricing"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;15.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"eur"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;13.25&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="nl"&gt;"stock"&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="nl"&gt;"pagination"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"page"&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="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good luck finding the nested &lt;code&gt;pricing&lt;/code&gt; field. Now imagine this is 500 lines long.&lt;/p&gt;

&lt;p&gt;Here are three tricks that save me hours every week when working with JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Pretty-Print First, Debug Later
&lt;/h2&gt;

&lt;p&gt;Before you even look at a JSON blob, format it. Most terminal users reach for &lt;code&gt;python -m json.tool&lt;/code&gt;, but that only handles valid JSON. If there's a trailing comma or a missing quote, it fails with an unhelpful error.&lt;/p&gt;

&lt;p&gt;A good JSON formatter shows you &lt;strong&gt;where&lt;/strong&gt; the syntax error is, not just that it exists. Missing closing bracket on line 47? An inline formatter catches that instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My workflow:&lt;/strong&gt; paste raw JSON → identify structural issues → read the formatted output → debug the logic. The formatting step takes 2 seconds but saves 10 minutes of squinting at minified blobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Collapse Deeply Nested Structures
&lt;/h2&gt;

&lt;p&gt;When an API response goes 4+ levels deep, the tree view is your best friend. Instead of scrolling through 200 lines, collapse everything and expand only the branch you're interested in.&lt;/p&gt;

&lt;p&gt;Most dev tools don't do this well, but a dedicated formatter with tree view lets you drill down to &lt;code&gt;response.data.items[3].metadata.pricing.usd&lt;/code&gt; in two clicks — without losing context of where you are in the structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Validate JSON Before It Reaches Production
&lt;/h2&gt;

&lt;p&gt;I've shipped config files with trailing commas more times than I'd like to admit. JSON is stricter than JavaScript — no trailing commas, no single quotes, no comments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trailing comma trap:&lt;/strong&gt; &lt;code&gt;{"key": "value",}&lt;/code&gt; works in JS but fails &lt;code&gt;JSON.parse()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-quote habit:&lt;/strong&gt; Switching between JS and JSON makes &lt;code&gt;{'key': 'value'}&lt;/code&gt; feel right — it's not&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Empty values:&lt;/strong&gt; &lt;code&gt;{"key": }&lt;/code&gt; or &lt;code&gt;{"key": NaN}&lt;/code&gt; — JSON doesn't support &lt;code&gt;undefined&lt;/code&gt; or &lt;code&gt;NaN&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A validator that pinpoints the exact character position of the error catches these before your CI pipeline does.&lt;/p&gt;




&lt;p&gt;I use &lt;a href="https://codetoolbox.pro/tools/json-formatter.html" rel="noopener noreferrer"&gt;CodeToolbox's JSON Formatter&lt;/a&gt; for all three — it handles formatting, tree view, and validation in one page, all client-side (nothing sent to a server).&lt;/p&gt;

&lt;p&gt;What's your go-to JSON debugging workflow?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Beyond UUID v4: v7, ULID, and the Future of Unique IDs</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Tue, 09 Jun 2026 13:03:33 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/beyond-uuid-v4-v7-ulid-and-the-future-of-unique-ids-542</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/beyond-uuid-v4-v7-ulid-and-the-future-of-unique-ids-542</guid>
      <description>&lt;p&gt;Most developers know UUIDs as those random 36-character strings useful for database keys. But the UUID landscape has evolved significantly — RFC 9562 (May 2024) introduced three new versions. If you're still defaulting to v4 without considering alternatives, you might be leaving performance on the table.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Classic: UUID v4
&lt;/h2&gt;

&lt;p&gt;UUID v4 generates 122 random bits. It's universally supported, cryptographically random, and requires zero coordination. The downside: random UUIDs fragment B-tree indexes, causing write amplification in high-throughput databases.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- PostgreSQL: native support since 8.3&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;UUID&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="n"&gt;JSONB&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Upgrade: UUID v7 (Time-Ordered)
&lt;/h2&gt;

&lt;p&gt;UUID v7 embeds a millisecond-precision Unix timestamp in the first 48 bits, followed by random bits for uniqueness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|--48 bits timestamp--|--4 ver--|--12 seq--|--62 random--|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this matters: &lt;strong&gt;time-sortable IDs are index-friendly.&lt;/strong&gt; Database pages stay compact, writes are sequential, and range queries (WHERE created &amp;gt; X) benefit enormously. In a real benchmark, PostgreSQL INSERT throughput with v7 was &lt;strong&gt;37% higher&lt;/strong&gt; than v4 under concurrent load.&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="c1"&gt;// uuid v7 (browser-native via crypto.randomUUID in some browsers)&lt;/span&gt;
&lt;span class="c1"&gt;// For broader support, use the uuid npm package&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;v7&lt;/span&gt; &lt;span class="p"&gt;}&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;uuid&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;v7&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "018f3a8c-..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Compact Alternative: ULID
&lt;/h2&gt;

&lt;p&gt;ULIDs are 26 characters (vs 36 for UUID), use Crockford base32 (URL-safe, no ambiguous characters), and are lexicographically sortable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01ARZ3NDEKTSV4RRFFQ69G5FAV  // ULID
018f3a8c-1e2d-7f3a-...      // UUID v7
550e8400-e29b-41d4-...      // UUID v4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Decision Framework
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;General purpose, max compatibility&lt;/td&gt;
&lt;td&gt;UUID v4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write-heavy DB, time-based queries&lt;/td&gt;
&lt;td&gt;UUID v7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;URL-safe, human-readable, compact&lt;/td&gt;
&lt;td&gt;ULID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security-sensitive (no timestamp leak)&lt;/td&gt;
&lt;td&gt;UUID v4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Quick Testing
&lt;/h2&gt;

&lt;p&gt;When choosing an ID scheme, I often generate batches to compare formats side by side. There's a free &lt;a href="https://codetoolbox.pro/tools/uuid-generator.html" rel="noopener noreferrer"&gt;UUID Generator&lt;/a&gt; that produces v4 UUIDs in bulk — useful for test fixtures, seed data, or just comparing the visual format against ULIDs. No signup, all browser-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;UUID v4 isn't wrong — it's the safe choice. But if you're building a write-heavy service in 2026, spending 5 minutes evaluating v7 or ULID could save you database pain down the road. The time-sortable formats are maturing fast, and most major libraries support them today.&lt;/p&gt;

</description>
      <category>database</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Cron Expressions for CI/CD — Beyond Crontab Basics</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Sat, 06 Jun 2026 13:03:31 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/cron-expressions-for-cicd-beyond-crontab-basics-3i1o</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/cron-expressions-for-cicd-beyond-crontab-basics-3i1o</guid>
      <description>&lt;p&gt;Most developers first encounter cron through &lt;code&gt;crontab -e&lt;/code&gt; on a Linux server. But cron syntax now powers schedules far beyond sysadmin scripts — it's the backbone of CI/CD automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cron in the Modern Stack
&lt;/h2&gt;

&lt;p&gt;Three tools you probably use today rely on cron expressions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Actions.&lt;/strong&gt; The &lt;code&gt;schedule&lt;/code&gt; trigger uses standard 5-field cron. This runs every weekday at 6 AM UTC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;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="s1"&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;6&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;&lt;strong&gt;Kubernetes CronJobs.&lt;/strong&gt; Same syntax, different YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;batch/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CronJob&lt;/span&gt;
&lt;span class="na"&gt;spec&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*/15&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;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AWS EventBridge / CloudWatch.&lt;/strong&gt; Cloud-native cron for serverless triggers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trick People Miss
&lt;/h2&gt;

&lt;p&gt;When both day-of-month AND day-of-week are specified (not &lt;code&gt;*&lt;/code&gt;), cron uses OR logic — the job fires when EITHER matches. This catches everyone:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0 0 1 * 1&lt;/code&gt; doesn't mean "the 1st of the month only if it's Monday." It means "run at midnight on the 1st of every month, AND also every Monday." If you meant the first scenario, set &lt;code&gt;day-of-week&lt;/code&gt; to &lt;code&gt;*&lt;/code&gt; and add date-checking logic in your script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Testing Tip
&lt;/h2&gt;

&lt;p&gt;Instead of waiting to see if your cron fires, use a visual generator to confirm the intent. I use &lt;a href="https://codetoolbox.pro/tools/cron-generator.html" rel="noopener noreferrer"&gt;CodeToolbox's Cron Expression Generator&lt;/a&gt; — pick the fields from dropdowns, read the plain-English description, and check the next 5 execution times before pasting into CI config. All browser-side, no signup needed.&lt;/p&gt;

&lt;p&gt;What cron mistake taught you a lesson the hard way?&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cron</category>
      <category>tutorial</category>
      <category>github</category>
    </item>
    <item>
      <title>Loan Math for Developers: 4 Levers That Save Thousands</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Thu, 04 Jun 2026 13:07:29 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/loan-math-for-developers-4-levers-that-save-thousands-2c0i</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/loan-math-for-developers-4-levers-that-save-thousands-2c0i</guid>
      <description>&lt;p&gt;If you've ever signed a mortgage, financed a car, or consolidated debt, you've encountered the amortization formula. It looks intimidating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;M = P * [r(1+r)^n] / [(1+r)^n - 1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But once you understand how each variable moves the needle, you can make decisions that save tens of thousands of dollars. Here's what every developer should know about loan math.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Formula, Deconstructed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;P&lt;/strong&gt; = principal (what you borrow)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;r&lt;/strong&gt; = monthly interest rate (annual rate / 12)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n&lt;/strong&gt; = total number of payments (years * 12)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;M&lt;/strong&gt; = your fixed monthly payment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The counterintuitive part: early payments are almost entirely interest. On a $250,000, 30-year mortgage at 6.5%, your first payment sends $1,354 to interest and only $226 to principal. By year 15, the split approaches 50/50. This front-loading is why extra payments early in the term have outsized impact.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Levers You Can Pull
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Extra Principal Payments
&lt;/h3&gt;

&lt;p&gt;Adding $100/month to the same mortgage saves ~$49,000 and knocks off 4.5 years. The earlier you start, the larger the compounding effect — because each extra dollar reduces the balance on which ALL future interest is calculated.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Biweekly Instead of Monthly
&lt;/h3&gt;

&lt;p&gt;Pay half the monthly amount every two weeks, and you sneak in one extra full payment per year (26 half-payments = 13 full). On a $250k loan, that's ~$53,000 saved and 4-5 years cut from the term — without feeling like you're paying more each month.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The 15-Year vs 30-Year Tradeoff
&lt;/h3&gt;

&lt;p&gt;Same $250k loan at 6.5%:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;30-year&lt;/strong&gt;: $1,580/month, $568,861 total — 56% of every dollar is interest&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;15-year&lt;/strong&gt;: $2,178/month, $392,069 total — saving $176,791&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The monthly jump is real, but the interest savings could buy you a second house.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Rate Shopping Actually Matters
&lt;/h3&gt;

&lt;p&gt;A 1% rate difference on a $250k mortgage = over $50,000 in extra interest across 30 years. That single percentage point costs more than most people spend on cars. Always compare APRs (which include fees), not just the advertised rate.&lt;/p&gt;




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

&lt;p&gt;I built a &lt;a href="https://codetoolbox.pro/tools/loan-calculator.html" rel="noopener noreferrer"&gt;Loan Calculator&lt;/a&gt; on CodeToolbox that lets you model any of these scenarios in seconds. Enter your numbers, hit Calculate, and you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monthly payment, total interest, and total cost instantly&lt;/li&gt;
&lt;li&gt;A visual pie chart showing principal-to-interest ratio&lt;/li&gt;
&lt;li&gt;A full amortization table with month-by-month and year-by-year breakdowns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All processing happens in your browser — no signup, no ads, your financial data never leaves your device.&lt;/p&gt;




&lt;p&gt;Understanding these four levers (extra payments, biweekly schedule, shorter term, rate shopping) is the difference between paying what the bank asks and paying what you actually need to. The calculator handles the math — you just need to know which knobs to turn.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>5 Regex Patterns That Will Save You Hours of Debugging</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Mon, 01 Jun 2026 13:03:24 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/5-regex-patterns-that-will-save-you-hours-of-debugging-1o1p</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/5-regex-patterns-that-will-save-you-hours-of-debugging-1o1p</guid>
      <description>&lt;p&gt;If you write code, you've been there — staring at a regex that &lt;em&gt;should&lt;/em&gt; work but doesn't. Meanwhile, Stack Overflow suggests nine different patterns, none of which match your actual data.&lt;/p&gt;

&lt;p&gt;Here are five regex patterns I reach for constantly. Each one has saved me real debugging time — the kind where you'd otherwise spend 20 minutes on a character that should have been escaped.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Extract Key-Value Pairs from Query Strings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;/&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="o"&gt;&amp;amp;=&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="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="o"&gt;^&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&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;g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parse &lt;code&gt;?page=3&amp;amp;sort=desc&amp;amp;tag=regex&lt;/code&gt; into &lt;code&gt;{page: "3", sort: "desc", tag: "regex"}&lt;/code&gt; in one line. Way cleaner than &lt;code&gt;split("&amp;amp;")&lt;/code&gt; → &lt;code&gt;split("=")&lt;/code&gt; loops.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Match Paired HTML Tags (Without Crossing Boundaries)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;/&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;^&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\\&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;g
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backreference &lt;code&gt;\\1&lt;/code&gt; ensures you match &lt;code&gt;&amp;lt;div&amp;gt;...&amp;lt;/div&amp;gt;&lt;/code&gt;, not &lt;code&gt;&amp;lt;div&amp;gt;...&amp;lt;/span&amp;gt;&lt;/code&gt;. This catches unbalanced tags that regex101 won't flag because it only tests one pattern at a time.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Validate ISO 8601 Dates (with Leap Year Awareness)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;/^&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;4&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&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="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&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="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&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="mi"&gt;01&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A quick sanity check before passing dates to &lt;code&gt;new Date()&lt;/code&gt;. Catches &lt;code&gt;2025-13-01&lt;/code&gt; (invalid month) and &lt;code&gt;2025-02-30&lt;/code&gt; (impossible day) that JavaScript silently coerces into valid dates.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Extract All Numbers (Including Decimals and Negatives)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;/-&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(?:&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)?&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;g
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Grabs &lt;code&gt;-3.14&lt;/code&gt;, &lt;code&gt;42&lt;/code&gt;, &lt;code&gt;0.001&lt;/code&gt; from mixed text. Use this when scraping prices, measurements, or coordinates from unstructured data.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Strip ANSI Escape Codes from Terminal Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\\&lt;/span&gt;&lt;span class="nx"&gt;x1b&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ever piped &lt;code&gt;npm test&lt;/code&gt; output to a file and got garbage? This pattern removes all color/formatting codes, leaving clean text you can parse or grep.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Tool That Makes This Fast
&lt;/h3&gt;

&lt;p&gt;I test every pattern above in &lt;a href="https://codetoolbox.pro/tools/regex-tester.html" rel="noopener noreferrer"&gt;CodeToolbox Regex Tester&lt;/a&gt; before pasting it into production code. Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instant visual feedback&lt;/strong&gt; — highlighted matches update as you type, so you see the greedy/lazy difference immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capture group breakdown&lt;/strong&gt; — each group is listed separately, so you know exactly what &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt; will contain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No data leaves your browser&lt;/strong&gt; — all processing is local JavaScript, so you can test on real log files and API responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No signup, no ads, no server uploads. Just a fast regex playground that stays out of your way.&lt;/p&gt;




&lt;p&gt;These five patterns cover ~80% of the regex work I do in a typical week. What's the one regex pattern you find yourself writing over and over? I'd love to add it to my toolkit 🙂&lt;/p&gt;

</description>
      <category>regex</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>encodeURI vs encodeURIComponent: The JavaScript URL Encoding Trap</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Sun, 31 May 2026 13:05:38 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/encodeuri-vs-encodeuricomponent-the-javascript-url-encoding-trap-13p</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/encodeuri-vs-encodeuricomponent-the-javascript-url-encoding-trap-13p</guid>
      <description>&lt;p&gt;Most JavaScript developers have been bitten by URL encoding at some point. You build a query string, pass it to &lt;code&gt;fetch()&lt;/code&gt;, and suddenly your API returns 400. The culprit? You used &lt;code&gt;encodeURI()&lt;/code&gt; when you should have used &lt;code&gt;encodeURIComponent()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Difference
&lt;/h2&gt;

&lt;p&gt;JavaScript gives us two encoding functions, and they serve different purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;encodeURI()&lt;/code&gt;&lt;/strong&gt; is designed for complete URLs. It keeps URL structure characters intact: &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;, &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;:&lt;/code&gt;, &lt;code&gt;@&lt;/code&gt;, &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, and &lt;code&gt;,&lt;/code&gt;. Use it when you have a full URL string and want to make it safe for transmission.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;encodeURIComponent()&lt;/code&gt;&lt;/strong&gt; is for individual parameter values. It encodes &lt;strong&gt;everything&lt;/strong&gt; except &lt;code&gt;A-Z a-z 0-9 - _ . ! ~ * ' ( )&lt;/code&gt;. This is what you want for query string values, path segments, and any data embedded in a URL.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Classic Bug
&lt;/h2&gt;

&lt;p&gt;Here's the mistake everyone makes at least once:&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="c1"&gt;// WRONG — the @ and = break as literal URL characters&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@example.com&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/search?email=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Result: https://api.example.com/search?email=user@example.com&lt;/span&gt;
&lt;span class="c1"&gt;// The @ is interpreted as a URL authority separator!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix:&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="c1"&gt;// RIGHT — all special chars are percent-encoded&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/search?email=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Result: https://api.example.com/search?email=user%40example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Double-Encoding: The Silent Killer
&lt;/h2&gt;

&lt;p&gt;If you encode an already-encoded string, the &lt;code&gt;%&lt;/code&gt; sign itself gets 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;. This is maddening to debug because it looks almost right. The fix: always decode first to see what you're actually working with.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Modern Approach
&lt;/h2&gt;

&lt;p&gt;In 2026, you rarely need to manually encode URLs. The &lt;code&gt;URL&lt;/code&gt; and &lt;code&gt;URLSearchParams&lt;/code&gt; APIs handle encoding automatically:&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;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user@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;q&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com/search?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// https://api.example.com/search?email=user%40example.com&amp;amp;q=hello+world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When You Still Need Manual Encoding
&lt;/h2&gt;

&lt;p&gt;Sometimes you're debugging logs, comparing API responses, or working with encoded strings from external systems. That's when a quick encoder/decoder tool saves you from counting percent signs in your terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handy tool:&lt;/strong&gt; I keep &lt;a href="https://codetoolbox.pro/tools/url-encoder.html" rel="noopener noreferrer"&gt;CodeToolbox URL Encoder&lt;/a&gt; bookmarked for those moments — paste any string, encode or decode instantly, all local processing so no data leaves your browser.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; &lt;code&gt;encodeURI()&lt;/code&gt; for full URLs. &lt;code&gt;encodeURIComponent()&lt;/code&gt; for values. &lt;code&gt;URLSearchParams&lt;/code&gt; for everything new. And if you see &lt;code&gt;%25&lt;/code&gt; in your output, you've double-encoded — decode and start over.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
