<?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>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>
    <item>
      <title>UUIDs in Practice — When Auto-Increment Falls Short</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Fri, 29 May 2026 13:05:09 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/uuids-in-practice-when-auto-increment-falls-short-5d6i</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/uuids-in-practice-when-auto-increment-falls-short-5d6i</guid>
      <description>&lt;p&gt;Most of us learned databases with auto-increment IDs. &lt;code&gt;id INT AUTO_INCREMENT&lt;/code&gt; is in every tutorial. It works — until it doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Case for Auto-Increment
&lt;/h2&gt;

&lt;p&gt;Auto-increment integers are fast, small (4 bytes), and naturally ordered. For a single-database app with one writer, they're perfect. But real systems rarely stay that simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Auto-Increment Fails
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Distributed writes.&lt;/strong&gt; When you have multiple API servers writing to the same database, auto-increment creates a bottleneck. Someone has to own the counter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-tenant databases.&lt;/strong&gt; Merging data from different shards or regions? Integer ID collisions are guaranteed. You'll spend days resolving conflicts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data exposure.&lt;/strong&gt; &lt;code&gt;/api/users/1&lt;/code&gt;, &lt;code&gt;/api/users/2&lt;/code&gt;... users and competitors can estimate your growth, user count, and order volume in minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Offline-first apps.&lt;/strong&gt; Can't generate IDs while disconnected if you need a central sequence. UUIDs work anywhere, anytime.&lt;/p&gt;

&lt;h2&gt;
  
  
  UUID v4: The Distributed-Friendly Default
&lt;/h2&gt;

&lt;p&gt;UUID v4 generates 122 random bits via a cryptographically secure PRNG — no coordination needed. The collision probability is astronomically low (1 in 2.7×10^18). PostgreSQL handles them natively:&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="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&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;email&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 16-byte storage overhead is negligible for modern systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trade-off
&lt;/h2&gt;

&lt;p&gt;UUIDs aren't sortable by insertion order and can fragment B-tree indexes. For write-heavy workloads, consider UUID v7 (time-ordered) or ULID. But for 95% of projects, v4 works fine.&lt;/p&gt;

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

&lt;p&gt;When setting up a new project, I generate a batch of UUIDs to copy into my seed files or test fixtures. There's a dead-simple generator at &lt;a href="https://codetoolbox.pro/tools/uuid-generator.html" rel="noopener noreferrer"&gt;codetoolbox.pro/tools/uuid-generator&lt;/a&gt; — no signup, no uploads, all browser-side. Just set the count and go.&lt;/p&gt;

&lt;p&gt;What do you use for primary keys in your projects?&lt;/p&gt;

</description>
      <category>database</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>How Loan Amortization Actually Works (and How to Save Thousands)</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Sun, 24 May 2026 13:03:25 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/how-loan-amortization-actually-works-and-how-to-save-thousands-i81</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/how-loan-amortization-actually-works-and-how-to-save-thousands-i81</guid>
      <description>&lt;p&gt;Most developers understand compound interest for investments. But with debt — mortgages, auto loans, student loans — the same math works against you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Formula Behind Every Loan Payment
&lt;/h2&gt;

&lt;p&gt;Every fixed-rate loan uses this amortization formula:&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;&lt;strong&gt;M&lt;/strong&gt; = monthly payment, &lt;strong&gt;P&lt;/strong&gt; = principal, &lt;strong&gt;r&lt;/strong&gt; = monthly rate (annual ÷ 12), &lt;strong&gt;n&lt;/strong&gt; = total payments.&lt;/p&gt;

&lt;p&gt;The intuition: this exact amount drives your balance to zero by the final payment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Front-Loading Trap
&lt;/h2&gt;

&lt;p&gt;On a $250k mortgage at 6.5% over 30 years, your first payment is roughly &lt;strong&gt;85% interest, 15% principal&lt;/strong&gt;. By year 15 it's 50/50. In the final year, over 95% goes to principal.&lt;/p&gt;

&lt;p&gt;This means every extra dollar toward principal early has an outsized effect. That $100 extra in month 1 saves you 359 months of interest on that $100.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;$250k at 6.5% / 30yr:&lt;/strong&gt; $1,580/mo, total $568,861&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same at 15yr:&lt;/strong&gt; $2,178/mo, total $392,069 → saves &lt;strong&gt;$176,792&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$100/mo extra on 30yr:&lt;/strong&gt; Saves ~$49k, pays off 4.5 years early&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3 Simple Strategies
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Bi-weekly payments:&lt;/strong&gt; 26 half-payments = 13 full payments/year. Knocks ~5 years off a 30yr mortgage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Round up:&lt;/strong&gt; Pay $1,600 instead of $1,580. The $20 extra compounds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refi but keep old payment:&lt;/strong&gt; When rates drop, keep paying the old amount. The difference is pure principal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I built a &lt;a href="https://codetoolbox.pro/tools/loan-calculator.html" rel="noopener noreferrer"&gt;free loan calculator&lt;/a&gt; with full amortization schedules and visual breakdowns. Runs in your browser, no signup.&lt;/p&gt;

&lt;p&gt;Understanding amortization isn't just for homeowners — car loans, personal loans, any installment debt. The math is identical. The earlier you act, the more you save.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>My 4-Step Regex Debugging Workflow (That Actually Saves Time)</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Thu, 21 May 2026 13:07:23 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/my-4-step-regex-debugging-workflow-that-actually-saves-time-58h5</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/my-4-step-regex-debugging-workflow-that-actually-saves-time-58h5</guid>
      <description>&lt;p&gt;I've written hundreds of regular expressions over the years, and I still get them wrong on the first try. Here's the debugging workflow I've settled on that consistently gets me from "why isn't this matching" to "oh, that's why" in under a minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Isolate One Pattern at a Time
&lt;/h2&gt;

&lt;p&gt;The most common mistake I see (and make) is testing a monster regex all at once. If you're validating an email with a complex pattern and it's not working, break it down: test just the local part, then the domain, then combine them. This alone has saved me hours of staring at a wall of backslashes and brackets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Check Your Quantifier Greediness
&lt;/h2&gt;

&lt;p&gt;This one bites everyone. A pattern like &lt;code&gt;&amp;lt;.*&amp;gt;&lt;/code&gt; against &lt;code&gt;"&amp;lt;div&amp;gt;hello&amp;lt;/div&amp;gt;"&lt;/code&gt; matches the &lt;em&gt;entire&lt;/em&gt; string, not just the opening tag. The fix: add &lt;code&gt;?&lt;/code&gt; to make it lazy — &lt;code&gt;&amp;lt;.*?&amp;gt;&lt;/code&gt;. I can't count how many "my regex is broken" posts on Stack Overflow boil down to this. Whenever a pattern matches too much, my first instinct is to check for greedy quantifiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Toggle the Flags
&lt;/h2&gt;

&lt;p&gt;Flags change everything. &lt;code&gt;hello&lt;/code&gt; matches "hello" — but add the &lt;code&gt;i&lt;/code&gt; flag and &lt;code&gt;hello&lt;/code&gt; now matches "HELLO", "Hello", and "hElLo". The &lt;code&gt;^&lt;/code&gt; anchor matches the start of a string by default, but with the &lt;code&gt;m&lt;/code&gt; (multiline) flag, it matches the start of &lt;em&gt;each line&lt;/em&gt;. I often toggle the &lt;code&gt;g&lt;/code&gt; (global) flag off during debugging to focus on the first match, then turn it back on to check all occurrences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Use a Real-Time Tester
&lt;/h2&gt;

&lt;p&gt;This is the game-changer. Rather than write-test-rewrite cycles in my code editor, I use a live regex tester that highlights matches as I type. Seeing matches highlighted instantly — and seeing capture groups broken out individually — makes pattern bugs obvious in seconds. I use &lt;a href="https://codetoolbox.pro/tools/regex-tester.html" rel="noopener noreferrer"&gt;CodeToolbox Regex Tester&lt;/a&gt; because it runs entirely in the browser (no data uploads) and includes presets for common patterns like email, URL, and IPv4 to use as starting points.&lt;/p&gt;




&lt;p&gt;The complete workflow takes less than a minute once it becomes habit: isolate → check greediness → toggle flags → test live. These four steps have saved me more debugging time than any regex cheatsheet ever has.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What's your go-to regex debugging trick? I'd love to hear what works for you in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>regex</category>
      <category>javascript</category>
      <category>debugging</category>
      <category>webdev</category>
    </item>
    <item>
      <title>5 Markdown Tricks Every Developer Should Know (That Aren't in the Cheat Sheet)</title>
      <dc:creator>zhihu wu</dc:creator>
      <pubDate>Tue, 19 May 2026 13:06:43 +0000</pubDate>
      <link>https://dev.to/zhihu_wu_dea1d82af01a04d7/5-markdown-tricks-every-developer-should-know-that-arent-in-the-cheat-sheet-23bh</link>
      <guid>https://dev.to/zhihu_wu_dea1d82af01a04d7/5-markdown-tricks-every-developer-should-know-that-arent-in-the-cheat-sheet-23bh</guid>
      <description>&lt;p&gt;We all know the basics: &lt;code&gt;**bold**&lt;/code&gt;, &lt;code&gt;*italic*&lt;/code&gt;, &lt;code&gt;# Headings&lt;/code&gt;. But Markdown (especially GitHub Flavored Markdown) has some lesser-known tricks that can make your READMEs, docs, and PR descriptions much more polished. Here are five I use constantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Collapsible Sections with &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Got a long README? Hide secondary content behind expandable sections:&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;Click to see the full changelog&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;

- v2.1: Added dark mode
- v2.0: Complete rewrite
- v1.0: Initial release

&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 toggle. Perfect for changelogs, setup instructions, or verbose examples you don't want cluttering the main view. GitHub, GitLab, and most static site generators support this.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Auto-Linking to Headings
&lt;/h2&gt;

&lt;p&gt;GitHub auto-generates anchor links for every heading. You can link to any section with a simple relative link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;See the &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Installation&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#installation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; section for setup instructions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule: lowercase everything, replace spaces with hyphens, remove punctuation. So &lt;code&gt;## API Reference (v2)&lt;/code&gt; becomes &lt;code&gt;#api-reference-v2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus:&lt;/strong&gt; This works across files too — &lt;code&gt;[See docs](docs/API.md#authentication)&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Task Lists in PR Descriptions
&lt;/h2&gt;

&lt;p&gt;GFM supports interactive checkboxes:&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] Add unit tests
&lt;span class="p"&gt;-&lt;/span&gt; [x] Update documentation
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Bump version number
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Deploy to staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These render as actual checkboxes on GitHub Issues and PRs. Use them in PR templates to create a checklist the author can tick off before merging. They also show up in project boards as trackable items.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Escaping Backticks Inside Inline Code
&lt;/h2&gt;

&lt;p&gt;Sometimes you need to show a literal backtick character inside inline code. The trick? Use &lt;strong&gt;double backticks&lt;/strong&gt; as delimiters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;To display a variable, use &lt;span class="sb"&gt;`` `varname` ``&lt;/span&gt; in your template.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Renders as: To display a variable, use &lt;code&gt;`varname`&lt;/code&gt; in your template.&lt;/p&gt;

&lt;p&gt;The outer double-backtick pair lets you nest single backticks inside. Add a space before/after the inner backtick for readability.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Mermaid Diagrams in Fenced Code Blocks
&lt;/h2&gt;

&lt;p&gt;Many platforms (GitHub, GitLab, Notion) support Mermaid diagrams directly in Markdown. Just use &lt;code&gt;mermaid&lt;/code&gt; as the language tag:&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;
&lt;/span&gt;
mermaid
graph TD
    A[User] --&amp;gt; B[Login Page]
    B --&amp;gt; C{Valid?}
    C --&amp;gt;|Yes| D[Dashboard]
    C --&amp;gt;|No| E[Error Message]


&lt;span class="p"&gt;```&lt;/span&gt;
&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;
&lt;/span&gt;
`

This renders a flowchart directly in your README — no external tools, no image exports. Mermaid supports flowcharts, sequence diagrams, Gantt charts, class diagrams, and more.

---

## The Best Way to Learn? Preview in Real Time

The fastest way to get comfortable with Markdown is to see it render as you type. I use [CodeToolbox Markdown Preview](https://codetoolbox.pro/tools/markdown-preview.html) when drafting READMEs — it's free, runs entirely in the browser (nothing gets uploaded), and supports full GFM including tables, task lists, and syntax-highlighted code blocks.

What Markdown tricks do you use that aren't in the standard cheat sheet? Drop them in the comments 👇
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>markdown</category>
      <category>github</category>
      <category>documentation</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
