<?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: Abu Sufyan</title>
    <description>The latest articles on DEV Community by Abu Sufyan (@abusufyan909).</description>
    <link>https://dev.to/abusufyan909</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%2F3676136%2Fc34098e0-95eb-4f86-a157-1e1b69e126e2.png</url>
      <title>DEV Community: Abu Sufyan</title>
      <link>https://dev.to/abusufyan909</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abusufyan909"/>
    <language>en</language>
    <item>
      <title>Stop using UUID v4 as your database primary key (and what to use instead)</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Fri, 26 Jun 2026 11:33:56 +0000</pubDate>
      <link>https://dev.to/abusufyan909/stop-using-uuid-v4-as-your-database-primary-key-and-what-to-use-instead-4o0m</link>
      <guid>https://dev.to/abusufyan909/stop-using-uuid-v4-as-your-database-primary-key-and-what-to-use-instead-4o0m</guid>
      <description>&lt;p&gt;You've been generating UUID v4 for your primary keys. It works. Nothing is on fire. But your database is slowly getting slower, and you might not have noticed why yet.&lt;/p&gt;

&lt;p&gt;Here's the short version: &lt;strong&gt;UUID v4 is completely random&lt;/strong&gt;. That sounds like a good thing until you realise what it does to your B-tree index.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's actually happening inside your database
&lt;/h2&gt;

&lt;p&gt;Every time you insert a row with a random UUID v4 as the primary key, PostgreSQL (or MySQL, or any B-tree-indexed store) has to find a random spot in the index to place it. Not at the end — &lt;em&gt;somewhere in the middle&lt;/em&gt;. Randomly. Every single time.&lt;/p&gt;

&lt;p&gt;This causes &lt;strong&gt;index fragmentation&lt;/strong&gt;. Over thousands of inserts, the index pages split constantly, fill unevenly, and require more I/O to read. On a small app you'll never notice. At 10M rows, you will.&lt;/p&gt;

&lt;p&gt;Here's what a v4 primary key sequence looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f47ac10b-58cc-4372-a567-0e02b2c3d479  ← random
3d4a2f1c-9b3e-4c7a-8d2e-1f5a9b3c7d2e  ← random
a1b2c3d4-e5f6-4789-abcd-ef0123456789  ← random
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every one of those lands in a different page of your index. PostgreSQL has to do a page lookup &lt;em&gt;every single insert&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  UUID v7 fixes this
&lt;/h2&gt;

&lt;p&gt;UUID v7 (standardised in RFC 9562) encodes a &lt;strong&gt;Unix millisecond timestamp in the first 48 bits&lt;/strong&gt;. The rest is still random — you still get global uniqueness — but because the timestamp comes first, rows generated close in time sort close together in the index.&lt;/p&gt;

&lt;p&gt;Here's what a v7 sequence looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;018f4b2c-1a00-7e3d-9b4f-2a1c3d5e7f9b  ← 2026-05-01 09:00:00.000
018f4b2c-1a01-7d2c-8a3e-1b2c4d6e8f0a  ← 2026-05-01 09:00:00.001
018f4b2c-1a02-7c1b-7b2d-0a1b3c5d7e9f  ← 2026-05-01 09:00:00.002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sequential. New rows go at the &lt;em&gt;end&lt;/em&gt; of the index, not scattered through it. Index pages fill cleanly. Fragmentation drops dramatically.&lt;/p&gt;

&lt;p&gt;The real-world impact: teams migrating from v4 to v7 primary keys have reported &lt;strong&gt;30–60% reduction in index bloat&lt;/strong&gt; on high-write tables. The write amplification on SSDs drops too.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to use v4 vs v7
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&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 unique ID (session tokens, correlation IDs, API responses)&lt;/td&gt;
&lt;td&gt;v4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database primary key on a high-write table&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;v7&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You need IDs to be sortable by creation time&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;v7&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;You want to obscure creation order from external users&lt;/td&gt;
&lt;td&gt;v4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distributed system, multiple writers, no coordination&lt;/td&gt;
&lt;td&gt;v7 (timestamp still prevents fragmentation)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you're starting a new project in 2026, &lt;strong&gt;default to v7 for primary keys&lt;/strong&gt;. The only reason to pick v4 is when you explicitly want non-sortable IDs (rate-limiting tokens, password reset links, etc.).&lt;/p&gt;




&lt;h2&gt;
  
  
  Generating them in code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JavaScript / Node.js (v7):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Node 22+ has experimental v7 support&lt;/span&gt;
&lt;span class="c1"&gt;// Until then, use the 'uuid' 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="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;uuidv7&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;uuidv7&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// → '018f4b2c-dead-7bee-beef-123456789abc'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;PostgreSQL native (requires pg_uuidv7 extension):&lt;/strong&gt;&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;SELECT&lt;/span&gt; &lt;span class="n"&gt;uuid_generate_v7&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Python:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid_utils&lt;/span&gt;  &lt;span class="c1"&gt;# pip install uuid-utils
&lt;/span&gt;
&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uuid_utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid7&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Quick sanity check — extract the timestamp from a v7:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;extractTimestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uuidV7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uuidV7&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/-/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;slice&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;12&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Need to generate a batch right now?
&lt;/h2&gt;

&lt;p&gt;If you're seeding a database, writing a migration script, or just need a stack of test UUIDs without installing anything — I built a free browser-based tool that handles both v4 and v7 bulk generation.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://wtkpro.site/tools/bulk-uuid-v4-v7-generator/" rel="noopener noreferrer"&gt;Bulk UUID v4 &amp;amp; v7 Generator — WebToolkit Pro&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything runs in your browser via &lt;code&gt;crypto.getRandomValues()&lt;/code&gt;. Nothing is sent to a server. Generate up to 100 at a time, copy them all in one click.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UUID v4 is random → random index positions → index fragmentation at scale&lt;/li&gt;
&lt;li&gt;UUID v7 is time-prefixed → sequential inserts → cleaner indexes, faster writes&lt;/li&gt;
&lt;li&gt;Use v7 for database primary keys, v4 for tokens and IDs that shouldn't be guessable&lt;/li&gt;
&lt;li&gt;Native browser generation with &lt;code&gt;crypto.getRandomValues()&lt;/code&gt; is already cryptographically secure — no library needed for v4; use the &lt;code&gt;uuid&lt;/code&gt; package for v7 until runtimes catch up&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Abu Sufyan is a full-stack developer and builder of &lt;a href="https://wtkpro.site" rel="noopener noreferrer"&gt;WebToolkit Pro&lt;/a&gt; — a free, privacy-first collection of 150+ client-side developer utilities.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A few weeks ago I started building WTKPro.</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Thu, 18 Jun 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/abusufyan909/a-few-weeks-ago-i-started-building-wtkpro-767</link>
      <guid>https://dev.to/abusufyan909/a-few-weeks-ago-i-started-building-wtkpro-767</guid>
      <description>&lt;p&gt;The goal wasn't to create another collection of generic tools.&lt;/p&gt;

&lt;p&gt;The goal was to build practical browser-based utilities that solve real problems for developers, students, and professionals.&lt;/p&gt;

&lt;p&gt;Current tools include:&lt;br&gt;
• JWT Decoder&lt;br&gt;
• JSON Formatter&lt;br&gt;
• Regex Tester&lt;br&gt;
• Image Resizer&lt;br&gt;
• SLA Breach Calculator&lt;br&gt;
• Unit Converter&lt;/p&gt;

&lt;p&gt;Every tool is built with speed, simplicity, and privacy in mind.&lt;/p&gt;

&lt;p&gt;Explore:&lt;br&gt;
&lt;a href="https://wtkpro.site/" rel="noopener noreferrer"&gt;https://wtkpro.site/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear which tools you'd like to see next.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Simple tools save time.</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Wed, 17 Jun 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/abusufyan909/simple-tools-save-time-mpm</link>
      <guid>https://dev.to/abusufyan909/simple-tools-save-time-mpm</guid>
      <description>&lt;p&gt;I built a Unit Converter that helps convert measurements quickly without ads, popups, or unnecessary complexity.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;br&gt;
• Students&lt;br&gt;
• Engineers&lt;br&gt;
• Developers&lt;br&gt;
• Everyday calculations&lt;/p&gt;

&lt;p&gt;Try it:&lt;br&gt;
&lt;a href="https://wtkpro.site/tools/unit-converter/" rel="noopener noreferrer"&gt;https://wtkpro.site/tools/unit-converter/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What conversions do you use most often?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Managing support teams often means tracking SLA performance.</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Tue, 16 Jun 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/abusufyan909/managing-support-teams-often-means-tracking-sla-performance-3nc3</link>
      <guid>https://dev.to/abusufyan909/managing-support-teams-often-means-tracking-sla-performance-3nc3</guid>
      <description>&lt;p&gt;I built an SLA Breach Calculator that helps teams calculate compliance rates, breach percentages, and service performance metrics.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;br&gt;
• IT Support&lt;br&gt;
• Customer Support&lt;br&gt;
• Service Desk Teams&lt;br&gt;
• Managed Service Providers&lt;/p&gt;

&lt;p&gt;Tool:&lt;br&gt;
&lt;a href="https://wtkpro.site/tools/sla-breach-calculator/" rel="noopener noreferrer"&gt;https://wtkpro.site/tools/sla-breach-calculator/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd appreciate feedback from anyone working in support operations.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>JavaScript Regex Multiline Guide 2026 — Fix Matching Errors Fast</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Tue, 16 Jun 2026 07:27:11 +0000</pubDate>
      <link>https://dev.to/abusufyan909/javascript-regex-multiline-guide-2026-fix-matching-errors-fast-3cj</link>
      <guid>https://dev.to/abusufyan909/javascript-regex-multiline-guide-2026-fix-matching-errors-fast-3cj</guid>
      <description>&lt;p&gt;description: "Fix JavaScript regex multiline matching errors in 3 steps. Covers the m flag, s flag (dotAll), and cross-platform line breaks (\r\n). Tested on Node 20."&lt;br&gt;
category: "Engineering"&lt;br&gt;
tags: ["JavaScript", "Regex", "Programming", "Web Development"]&lt;br&gt;
keywords: ["javascript regex multiline guide 2026", "regex multiline match", "javascript dotall flag", "regex m flag", "match across multiple lines javascript"]&lt;br&gt;
readTime: '6 min read'&lt;br&gt;
tldr: "To match text across multiple lines in JavaScript, you must understand the difference between the &lt;code&gt;m&lt;/code&gt; (multiline) flag, which modifies how &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; work, and the &lt;code&gt;s&lt;/code&gt; (dotAll) flag, which allows the &lt;code&gt;.&lt;/code&gt; character to match newline characters. Using &lt;code&gt;[\\s\\S]&lt;/code&gt; is the legacy fallback."&lt;br&gt;
author: "Abu Sufyan"&lt;br&gt;
image: "/blog/regex-multiline-guide.jpg"&lt;br&gt;
imageAlt: "JavaScript Regex Multiline matching code example"&lt;br&gt;
expertTips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Use the &lt;code&gt;s&lt;/code&gt; (dotAll) flag instead of the legacy &lt;code&gt;[\\s\\S]&lt;/code&gt; hack for better readability and performance in modern V8 engines."&lt;/li&gt;
&lt;li&gt;"Always account for Windows (&lt;code&gt;\\r\\n&lt;/code&gt;) and Unix (&lt;code&gt;\\n&lt;/code&gt;) line endings by using &lt;code&gt;\\r?\\n&lt;/code&gt; when explicitly matching line breaks."
faqs:&lt;/li&gt;
&lt;li&gt;q: "What does the m flag do in JavaScript regex?"
a: "The &lt;code&gt;m&lt;/code&gt; (multiline) flag changes the behavior of the &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; anchors. Instead of matching only the absolute start and end of the entire string, they will match the start and end of each individual line within the string."&lt;/li&gt;
&lt;li&gt;q: "How do I match a dot across multiple lines in JavaScript?"
a: "Use the &lt;code&gt;s&lt;/code&gt; (dotAll) flag. For example, &lt;code&gt;/foo.*bar/s&lt;/code&gt;. This allows the dot &lt;code&gt;.&lt;/code&gt; character to match newline characters (&lt;code&gt;\\n&lt;/code&gt;), which it normally ignores."&lt;/li&gt;
&lt;li&gt;q: "Is the s flag supported in all browsers?"
a: "Yes, the &lt;code&gt;s&lt;/code&gt; (dotAll) flag is fully supported in all modern browsers (Chrome 68+, Firefox 78+, Safari 11.1+) and Node.js v9+ as of 2026."&lt;/li&gt;
&lt;li&gt;q: "How do I replace all newlines in a string using regex?"
a: "You can use the global flag with the newline characters: &lt;code&gt;text.replace(/\\r?\\n/g, ' ')&lt;/code&gt;. This replaces all line breaks with a single space."
steps:&lt;/li&gt;
&lt;li&gt;name: "Understand the m flag"
text: "Learn how the m flag modifies anchor behavior."&lt;/li&gt;
&lt;li&gt;name: "Understand the s flag"
text: "Learn how the s flag enables dotAll matching."&lt;/li&gt;
&lt;li&gt;name: "Combine flags safely"
text: "Use m and s flags together for complex multiline extraction."
type: "blog"
---&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  JavaScript Regex Multiline Guide 2026 — Fix Matching Errors Fast
&lt;/h1&gt;

&lt;p&gt;A missing regex flag caused our markdown parser to silently drop half of our documentation pages during a migration. Here is the exact fix — and why multiline matching in JavaScript is so commonly misunderstood.&lt;/p&gt;

&lt;p&gt;I've been using JavaScript regular expressions for over 8 years, and multiline string parsing remains one of the most frequent causes of silent bugs in data extraction pipelines. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript regex multiline matching&lt;/strong&gt; is the process of finding patterns that span across multiple lines of text, or anchoring patterns to the start/end of individual lines within a larger string. It works by utilizing two specific flags: &lt;code&gt;m&lt;/code&gt; (multiline) and &lt;code&gt;s&lt;/code&gt; (dotAll). In 2026, the standard approach is to use the &lt;code&gt;s&lt;/code&gt; flag rather than legacy whitespace hacks.&lt;/p&gt;

&lt;p&gt;TL;DR: The fix is using the correct flag for your goal. To make &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; match per line, add the &lt;code&gt;m&lt;/code&gt; flag. To make &lt;code&gt;.&lt;/code&gt; match across newlines, add the &lt;code&gt;s&lt;/code&gt; flag. Example: &lt;code&gt;/pattern/ms&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Is Multiline Regex Matching?
&lt;/h2&gt;

&lt;p&gt;JavaScript regex multiline matching allows your pattern to correctly process strings containing newline characters (&lt;code&gt;\n&lt;/code&gt; or &lt;code&gt;\r\n&lt;/code&gt;). By default, JavaScript regex engines treat a string as one single continuous block, where &lt;code&gt;.&lt;/code&gt; stops at a newline, and &lt;code&gt;^&lt;/code&gt;/&lt;code&gt;$&lt;/code&gt; only match the absolute beginning and end of the file. If you are new to V8 engine execution rules, read our &lt;a href="https://dev.to/blog/regex-cheat-sheet-javascript/"&gt;JS Regex Cheat Sheet&lt;/a&gt; for a full primer.&lt;/p&gt;

&lt;p&gt;When you parse CSV files, markdown documents, or raw HTTP responses, you are dealing with multiline strings. If you don't explicitly tell the V8 regex engine how to handle those newlines, your data extraction will fail.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Multiline Regex Matters / The Problem It Solves
&lt;/h2&gt;

&lt;p&gt;Imagine you are writing a script to extract all &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; tags from an HTML document. You write a regex like &lt;code&gt;/&amp;lt;h2[^&amp;gt;]*&amp;gt;.*&amp;lt;\/h2&amp;gt;/g&lt;/code&gt;. It works perfectly in your unit tests. &lt;/p&gt;

&lt;p&gt;But in production, a user formats their HTML with a line break inside the &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; tag:&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;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;My Header&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suddenly, your regex completely misses this header. Your table of contents generates incorrectly, and users complain about missing sections. This happens because the &lt;code&gt;.&lt;/code&gt; character in JavaScript regex &lt;strong&gt;does not match newline characters by default&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Match Across Multiple Lines — Step by Step
&lt;/h2&gt;

&lt;p&gt;To fix multiline parsing errors, you need to apply the correct flags. As covered in our &lt;a href="https://dev.to/blog/performance-optimization-guide/"&gt;performance optimization guide&lt;/a&gt;, choosing the right flags avoids unnecessary string traversal overhead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Node.js v20+ or any modern browser&lt;/li&gt;
&lt;li&gt;A basic understanding of regex syntax&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1 — Use the &lt;code&gt;m&lt;/code&gt; (multiline) flag for Anchors
&lt;/h3&gt;

&lt;p&gt;If you want to extract the first word of every line, you need the &lt;code&gt;^&lt;/code&gt; anchor to trigger at the start of &lt;em&gt;each line&lt;/em&gt;, not just the start of the string.&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`apple is red
banana is yellow
cherry is red`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Without 'm' flag: Only matches "apple"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;noFlag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="c1"&gt;// With 'm' flag: Matches "apple", "banana", "cherry"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withMFlag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="sr"&gt;+/gm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ← add this line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output with the &lt;code&gt;m&lt;/code&gt; flag: &lt;code&gt;['apple', 'banana', 'cherry']&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Use the &lt;code&gt;s&lt;/code&gt; (dotAll) flag for Spanning Lines
&lt;/h3&gt;

&lt;p&gt;If you want to capture everything between two delimiters, even if there are newlines between them, use the &lt;code&gt;s&lt;/code&gt; flag.&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;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;div class="content"&amp;gt;
  &amp;lt;p&amp;gt;Hello World&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Fails because '.' stops at the first newline&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;failMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;div class="content"&amp;gt;.*&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;div&amp;gt;/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Succeeds because 's' makes '.' match newlines&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;successMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;div class="content"&amp;gt;.*&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;div&amp;gt;/&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ← add this line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;s&lt;/code&gt; flag is the modern 2026 standard for spanning lines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — The Legacy Fallback (&lt;code&gt;[\s\S]&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;If you are maintaining a legacy codebase (older than ES2018 / Node.js 9) where the &lt;code&gt;s&lt;/code&gt; flag is not supported, you must use the &lt;code&gt;[\s\S]&lt;/code&gt; character class hack.&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;// Matches any whitespace OR any non-whitespace (effectively matching everything including newlines)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;legacyMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&amp;lt;div class="content"&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;[\s\S]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;div&amp;gt;/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success confirmed. However, migrate to the &lt;code&gt;s&lt;/code&gt; flag when possible for cleaner syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Multiline Regex Errors and How to Fix Them
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Error 1 — Missing matches on Windows line endings
&lt;/h3&gt;

&lt;p&gt;Cause: Windows uses &lt;code&gt;\r\n&lt;/code&gt; for newlines, while Unix/Linux uses &lt;code&gt;\n&lt;/code&gt;. If your regex explicitly looks for &lt;code&gt;\n&lt;/code&gt;, it will fail on Windows files.&lt;br&gt;
Fix: Use &lt;code&gt;\r?\n&lt;/code&gt; to make the carriage return optional.&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;extractLines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\r?\n&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Error 2 — Greedy matching consuming the whole file
&lt;/h3&gt;

&lt;p&gt;Cause: When using the &lt;code&gt;s&lt;/code&gt; flag with a greedy &lt;code&gt;.*&lt;/code&gt;, the engine will consume the entire document up to the &lt;em&gt;last&lt;/em&gt; matching closing tag, rather than stopping at the first one.&lt;br&gt;
Fix: Make the quantifier lazy by adding &lt;code&gt;?&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BAD: Consumes from the first &amp;lt;div&amp;gt; to the very last &amp;lt;/div&amp;gt; in the file&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greedy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&amp;lt;div&amp;gt;.*&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;div&amp;gt;/&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// GOOD: Stops at the first closing &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lazy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&amp;lt;div&amp;gt;.*&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;&amp;lt;&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;div&amp;gt;/&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Multiline Regex Best Practices in 2026
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always prefer the &lt;code&gt;s&lt;/code&gt; flag over &lt;code&gt;[\s\S]&lt;/code&gt;.&lt;/strong&gt; It clearly communicates your intent to other developers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use &lt;code&gt;trim()&lt;/code&gt; before applying line-start anchors.&lt;/strong&gt; Invisible leading whitespace will cause &lt;code&gt;^&lt;/code&gt; anchors to fail if you aren't careful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't use Regex for complex HTML parsing.&lt;/strong&gt; If you are parsing nested, deeply multiline HTML, use a proper DOM parser like &lt;code&gt;cheerio&lt;/code&gt; or &lt;code&gt;JSDOM&lt;/code&gt;. Regex cannot accurately parse nested recursive structures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;s&lt;/code&gt; Flag vs &lt;code&gt;[\s\S]&lt;/code&gt; Hack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;s&lt;/code&gt; Flag (dotAll)&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;[\s\S]&lt;/code&gt; Hack&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Tie&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Readability&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Poor&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;s&lt;/code&gt; Flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compatibility&lt;/td&gt;
&lt;td&gt;ES2018+&lt;/td&gt;
&lt;td&gt;Universal&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;[\s\S]&lt;/code&gt; Hack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intent&lt;/td&gt;
&lt;td&gt;Explicit&lt;/td&gt;
&lt;td&gt;Implicit&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;s&lt;/code&gt; Flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Modern 2026 Stacks&lt;/td&gt;
&lt;td&gt;Legacy IE11/Node 8 Code&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;s&lt;/code&gt; Flag&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The clear winner for any modern development environment is the &lt;code&gt;s&lt;/code&gt; flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience Using Multiline Regex — Honest Verdict
&lt;/h2&gt;

&lt;p&gt;What I liked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The addition of the &lt;code&gt;s&lt;/code&gt; (dotAll) flag in ES2018 finally fixed the most annoying quirk of JavaScript regex. It makes payload extraction significantly cleaner.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;m&lt;/code&gt; flag is incredibly reliable for parsing &lt;code&gt;.env&lt;/code&gt; files or CSV line items locally without needing a heavy parser library.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What frustrated me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The fact that &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; don't default to per-line matching still trips up junior developers.&lt;/li&gt;
&lt;li&gt;Debugging multiline regex failures in production logs is painful because standard log aggregators often strip or mangle newline characters, making it impossible to reproduce the exact string state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Who I'd recommend it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers building lightweight markdown parsers, log analyzers, or scraping scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Who should look elsewhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teams trying to parse complex, user-generated HTML. Use a dedicated HTML parser instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;Q: What does the m flag do in JavaScript regex?&lt;br&gt;
A: The &lt;code&gt;m&lt;/code&gt; (multiline) flag changes the behavior of the &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt; anchors. Instead of matching only the absolute start and end of the entire string, they will match the start and end of each individual line within the string.&lt;/p&gt;

&lt;p&gt;Q: How do I match a dot across multiple lines in JavaScript?&lt;br&gt;
A: Use the &lt;code&gt;s&lt;/code&gt; (dotAll) flag. For example, &lt;code&gt;/foo.*bar/s&lt;/code&gt;. This allows the dot &lt;code&gt;.&lt;/code&gt; character to match newline characters (&lt;code&gt;\n&lt;/code&gt;), which it normally ignores.&lt;/p&gt;

&lt;p&gt;Q: Is the s flag supported in all browsers?&lt;br&gt;
A: Yes, the &lt;code&gt;s&lt;/code&gt; (dotAll) flag is fully supported in all modern browsers (Chrome 68+, Firefox 78+, Safari 11.1+) and Node.js v9+ as of 2026.&lt;/p&gt;

&lt;p&gt;Q: How do I replace all newlines in a string using regex?&lt;br&gt;
A: You can use the global flag with the newline characters: &lt;code&gt;text.replace(/\r?\n/g, ' ')&lt;/code&gt;. This replaces all line breaks with a single space.&lt;/p&gt;




&lt;p&gt;Try our free &lt;a href="https://dev.to/tools/regex-tester/"&gt;RegEx Tester &amp;amp; AI Explainer&lt;/a&gt; to validate your multiline patterns instantly →&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Abu Sufyan&lt;/strong&gt; · Full-stack developer · Founder of WebToolkit Pro&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/abusufyan-wtkpro/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last updated: 2026-06-16&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I spent too much time debugging regular expressions.</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Mon, 15 Jun 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/abusufyan909/i-spent-too-much-time-debugging-regular-expressions-1peb</link>
      <guid>https://dev.to/abusufyan909/i-spent-too-much-time-debugging-regular-expressions-1peb</guid>
      <description>&lt;p&gt;That's why I built a Regex Tester that highlights matches in real time and makes testing patterns much easier.&lt;/p&gt;

&lt;p&gt;Features:&lt;br&gt;
• Instant matching&lt;br&gt;
• Pattern testing&lt;br&gt;
• Visual feedback&lt;br&gt;
• No installation required&lt;/p&gt;

&lt;p&gt;Try it:&lt;br&gt;
&lt;a href="https://wtkpro.site/tools/regex-tester/" rel="noopener noreferrer"&gt;https://wtkpro.site/tools/regex-tester/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Regex experts: what features do you look for in a testing tool?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Working with APIs usually means dealing with messy JSON.</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Sun, 14 Jun 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/abusufyan909/working-with-apis-usually-means-dealing-with-messy-json-2688</link>
      <guid>https://dev.to/abusufyan909/working-with-apis-usually-means-dealing-with-messy-json-2688</guid>
      <description>&lt;p&gt;To make debugging easier, I built a JSON Formatter &amp;amp; Validator that instantly formats and validates JSON data.&lt;/p&gt;

&lt;p&gt;Features:&lt;br&gt;
✓ Pretty-print JSON&lt;br&gt;
✓ Error detection&lt;br&gt;
✓ Fast validation&lt;br&gt;
✓ Browser-based processing&lt;/p&gt;

&lt;p&gt;Tool:&lt;br&gt;
&lt;a href="https://wtkpro.site/tools/json-formatter/" rel="noopener noreferrer"&gt;https://wtkpro.site/tools/json-formatter/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What JSON features would you like to see added?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Stop pasting JWTs into random websites.</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Sat, 13 Jun 2026 07:50:00 +0000</pubDate>
      <link>https://dev.to/abusufyan909/stop-pasting-jwts-into-random-websites-8no</link>
      <guid>https://dev.to/abusufyan909/stop-pasting-jwts-into-random-websites-8no</guid>
      <description>&lt;p&gt;While debugging authentication issues, I realized many developers upload sensitive JWT tokens to third-party tools without thinking twice.&lt;/p&gt;

&lt;p&gt;So I built a browser-based JWT Decoder that processes tokens locally and helps inspect headers, payloads, and expiration dates quickly.&lt;/p&gt;

&lt;p&gt;Features:&lt;br&gt;
✅ Instant decoding&lt;br&gt;
✅ No account required&lt;br&gt;
✅ Clean interface&lt;br&gt;
✅ Works directly in your browser&lt;/p&gt;

&lt;p&gt;Try it here:&lt;br&gt;
&lt;a href="https://wtkpro.site/tools/jwt-decoder/" rel="noopener noreferrer"&gt;https://wtkpro.site/tools/jwt-decoder/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love feedback from fellow developers.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Free Online Tool to Resize Images Without Upload Limits</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Sat, 13 Jun 2026 06:45:51 +0000</pubDate>
      <link>https://dev.to/abusufyan909/free-online-tool-to-resize-images-without-upload-limits-3p91</link>
      <guid>https://dev.to/abusufyan909/free-online-tool-to-resize-images-without-upload-limits-3p91</guid>
      <description>&lt;p&gt;If you need a quick way to resize images for websites, social media, or documents, I recently built an online tool resize image utility that works directly in your browser.&lt;/p&gt;

&lt;p&gt;Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resize by pixels or percentage&lt;/li&gt;
&lt;li&gt;Fast processing&lt;/li&gt;
&lt;li&gt;No software installation&lt;/li&gt;
&lt;li&gt;Works on desktop and mobile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try it here:&lt;br&gt;
&lt;a href="https://wtkpro.site/tools/image-resizer/" rel="noopener noreferrer"&gt;https://wtkpro.site/tools/image-resizer/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback is welcome!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Cron Expression Guide — Examples &amp; Generator 2026</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Mon, 08 Jun 2026 07:30:00 +0000</pubDate>
      <link>https://dev.to/abusufyan909/cron-expression-guide-examples-generator-2026-2ma3</link>
      <guid>https://dev.to/abusufyan909/cron-expression-guide-examples-generator-2026-2ma3</guid>
      <description>&lt;p&gt;✓ Last tested: June 2026 · Verified against standard Vixie Cron implementation&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Field Notes: The Timezone Trap
&lt;/h2&gt;

&lt;p&gt;Early in my career, I deployed a database backup script using a cron job set to &lt;code&gt;0 2 * * *&lt;/code&gt; (2:00 AM daily). I wanted the backup to happen during the lowest traffic window for our US-based users.&lt;/p&gt;

&lt;p&gt;A week later, the database crashed at 9:00 PM EST due to IO exhaustion. Why? The AWS EC2 instance was running in UTC. 2:00 AM UTC is 9:00 PM EST—smack in the middle of prime time. &lt;/p&gt;

&lt;p&gt;The lesson? A cron expression is just a string of characters. It has no concept of geography. You must always align your cron schedules to the server's local timezone configuration, which in 2026 should always be UTC.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Cron Expression Syntax — The 5 Fields Explained
&lt;/h2&gt;

&lt;p&gt;A standard cron expression consists of five fields separated by spaces. (Some systems, like AWS CloudWatch or Quartz, use 6 fields to include seconds or years, but standard Linux cron uses 5).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* * * * *
│ │ │ │ │
│ │ │ │ └── Day of the week (0 - 7) (0 and 7 are both Sunday)
│ │ │ └──── Month (1 - 12)
│ │ └────── Day of the month (1 - 31)
│ └──────── Hour (0 - 23)
└────────── Minute (0 - 59)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Special Characters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;*&lt;/code&gt; (Asterisk): Matches all values. (e.g., &lt;code&gt;*&lt;/code&gt; in the hour field means "every hour").&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;,&lt;/code&gt; (Comma): Separates items in a list. (e.g., &lt;code&gt;1,15&lt;/code&gt; in the minute field means "at minute 1 and 15").&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;-&lt;/code&gt; (Hyphen): Defines a range. (e.g., &lt;code&gt;9-17&lt;/code&gt; in the hour field means "between 9 AM and 5 PM").&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/&lt;/code&gt; (Slash): Specifies increments. (e.g., &lt;code&gt;*/10&lt;/code&gt; in the minute field means "every 10 minutes").&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. 20 Ready-to-Use Cron Expression Examples
&lt;/h2&gt;

&lt;p&gt;Stop guessing. Here are the most common schedules you will actually use in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  High Frequency
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Every minute:&lt;/strong&gt; &lt;code&gt;* * * * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Every 5 minutes:&lt;/strong&gt; &lt;code&gt;*/5 * * * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Every 15 minutes:&lt;/strong&gt; &lt;code&gt;*/15 * * * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Every 30 minutes:&lt;/strong&gt; &lt;code&gt;*/30 * * * *&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Hourly Schedules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Every hour, on the hour:&lt;/strong&gt; &lt;code&gt;0 * * * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Every 2 hours:&lt;/strong&gt; &lt;code&gt;0 */2 * * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;At minute 15 past every hour:&lt;/strong&gt; &lt;code&gt;15 * * * *&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Daily Schedules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Midnight every day:&lt;/strong&gt; &lt;code&gt;0 0 * * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Every day at 2:30 AM:&lt;/strong&gt; &lt;code&gt;30 2 * * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Every day at 8:00 AM and 8:00 PM:&lt;/strong&gt; &lt;code&gt;0 8,20 * * *&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Weekly Schedules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Every Sunday at midnight:&lt;/strong&gt; &lt;code&gt;0 0 * * 0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Every Monday at 9:00 AM:&lt;/strong&gt; &lt;code&gt;0 9 * * 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Monday through Friday at 5:00 PM (Business close):&lt;/strong&gt; &lt;code&gt;0 17 * * 1-5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Weekends only, at noon:&lt;/strong&gt; &lt;code&gt;0 12 * * 0,6&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Monthly / Yearly Schedules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;First day of every month at midnight:&lt;/strong&gt; &lt;code&gt;0 0 1 * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;15th of every month at 3:00 AM:&lt;/strong&gt; &lt;code&gt;0 3 15 * *&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;January 1st at midnight (Happy New Year):&lt;/strong&gt; &lt;code&gt;0 0 1 1 *&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Cron in Kubernetes — What's Different?
&lt;/h2&gt;

&lt;p&gt;If you are writing a Kubernetes &lt;code&gt;CronJob&lt;/code&gt; manifest, the syntax is identical to standard Linux cron. However, Kubernetes adds a crucial behavior parameter: &lt;code&gt;concurrencyPolicy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If your job takes 10 minutes to run, but your cron is scheduled every 5 minutes (&lt;code&gt;*/5 * * * *&lt;/code&gt;), Kubernetes will overlap the pods. You must set &lt;code&gt;concurrencyPolicy: Forbid&lt;/code&gt; in your YAML if your script cannot handle concurrent executions safely.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Common Cron Expression Mistakes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;The Day/Date OR Trap:&lt;/strong&gt; If you write &lt;code&gt;0 0 1 * 1&lt;/code&gt;, you might think this means "Run at midnight on the first of the month, BUT ONLY if it's a Monday." Wrong. It means "Run on the first of the month, OR if it is a Monday."&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Using Seconds:&lt;/strong&gt; Writing &lt;code&gt;0 * * * * *&lt;/code&gt; (6 fields) will crash standard crontab, as it expects 5 fields.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Environment Variables:&lt;/strong&gt; Scripts run by cron execute in a highly restricted shell. Your &lt;code&gt;~/.bashrc&lt;/code&gt; is not loaded. Always use absolute paths to node/python binaries inside your scripts.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Need to translate a complex schedule into cron syntax? Use our free &lt;a href="https://wtkpro.site/" rel="noopener noreferrer"&gt;Cron Expression Generator&lt;/a&gt; to build and validate your schedule instantly →&lt;/p&gt;




&lt;h2&gt;
  
  
  External Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/community/CronHowto" rel="noopener noreferrer"&gt;Ubuntu Cron How-To&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/" rel="noopener noreferrer"&gt;Kubernetes CronJob Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Abu Sufyan&lt;/strong&gt; · Full-stack developer · Founder of WebToolkit Pro&lt;br&gt;
&lt;a href="https://github.com/abusufyan-netizen" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last updated: June 2026&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://wtkpro.site/blog/cron-expression-guide-examples/" rel="noopener noreferrer"&gt;WebToolkit Pro&lt;/a&gt;. Explore our suite of 145+ free, privacy-first developer utilities at &lt;a href="https://wtkpro.site/" rel="noopener noreferrer"&gt;wtkpro.site&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cron</category>
      <category>linux</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>Canonical URL SEO Guide — Fix Duplicate Content 2026</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Sun, 07 Jun 2026 07:28:27 +0000</pubDate>
      <link>https://dev.to/abusufyan909/canonical-url-seo-guide-fix-duplicate-content-2026-247a</link>
      <guid>https://dev.to/abusufyan909/canonical-url-seo-guide-fix-duplicate-content-2026-247a</guid>
      <description>&lt;p&gt;✓ Last tested: June 2026 · Verified against Google Search Central Guidelines&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Field Notes: The E-Commerce Parameter Nightmare
&lt;/h2&gt;

&lt;p&gt;I once audited an e-commerce site that was struggling to rank for "leather boots." When I checked Google Search Console, I saw that Google had indexed 45 different versions of their leather boots category page. &lt;/p&gt;

&lt;p&gt;Why? Because their filtering system appended parameters to the URL: &lt;code&gt;?sort=price_asc&lt;/code&gt;, &lt;code&gt;?color=brown&lt;/code&gt;, &lt;code&gt;?size=10&lt;/code&gt;. Because there were no canonical tags, Googlebot treated every filter combination as a unique page, diluting the ranking power (link equity) across 45 identical pages.&lt;/p&gt;

&lt;p&gt;We deployed absolute, self-referencing canonical tags on the clean URL, and pointed all parameter variations back to that clean URL. Within a month, the consolidated link equity pushed the main category page to page 1.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. What Is a Canonical URL and Why Does It Matter?
&lt;/h2&gt;

&lt;p&gt;A canonical URL is an HTML link tag with the attribute &lt;code&gt;rel="canonical"&lt;/code&gt;. It tells search engines: &lt;em&gt;"I know there are multiple ways to access this content, but THIS is the official version I want you to index and rank."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It prevents &lt;strong&gt;duplicate content issues&lt;/strong&gt;. Google hates duplicate content because it forces them to waste crawl budget and makes it difficult to decide which page to rank. &lt;/p&gt;




&lt;h2&gt;
  
  
  3. Common Duplicate Content Problems That Need Canonicals
&lt;/h2&gt;

&lt;p&gt;Even if you don't deliberately create duplicate content, your server might do it automatically. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Issue&lt;/th&gt;
&lt;th&gt;Variant A&lt;/th&gt;
&lt;th&gt;Variant B (Duplicate)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WWW vs Non-WWW&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://example.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://www.example.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP vs HTTPS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://example.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://example.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trailing Slash&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://example.com/blog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://example.com/blog/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tracking Parameters&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://example.com/sale&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://example.com/sale?utm_source=twitter&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Capitalization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://example.com/Products&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://example.com/products&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A self-referencing canonical tag fixes almost all of these (though server-level 301 redirects are preferred for HTTP/HTTPS and WWW issues).&lt;/p&gt;




&lt;h2&gt;
  
  
  4. How to Add a Canonical Tag
&lt;/h2&gt;

&lt;p&gt;The canonical tag must be placed in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; section of your HTML document.&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"canonical"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://example.com/leather-boots/"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;



&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"canonical"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://example.com/leather-boots/"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementing in Next.js (App Router)
&lt;/h3&gt;

&lt;p&gt;Next.js makes this easy with the Metadata API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;alternates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/leather-boots/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Canonical Tag Mistakes That Confuse Google
&lt;/h2&gt;

&lt;p&gt;Google treats the canonical tag as a &lt;em&gt;hint&lt;/em&gt;, not an absolute directive. If you implement it poorly, Google will ignore it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Relative URLs:&lt;/strong&gt; Always use absolute URLs. &lt;code&gt;href="https://wtkpro.site/"&lt;/code&gt; is wrong. &lt;code&gt;href="https://site.com/about"&lt;/code&gt; is correct.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Multiple Canonicals:&lt;/strong&gt; Having two canonical tags on one page (often caused by a CMS plugin conflict) will cause Google to ignore both.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Canonicalizing to a 404/301:&lt;/strong&gt; The canonical URL must return a &lt;code&gt;200 OK&lt;/code&gt; status.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Canonical + Noindex Conflict:&lt;/strong&gt; Do not put a &lt;code&gt;&amp;lt;meta name="robots" content="noindex"&amp;gt;&lt;/code&gt; on a page and then add a canonical tag pointing to another page. Choose one.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Cross-Domain Canonicalization
&lt;/h2&gt;

&lt;p&gt;If you write an article on your blog and syndicate it to Medium, Substack, or Dev.to, you risk those platforms outranking your own website.&lt;/p&gt;

&lt;p&gt;To fix this, you must set a &lt;strong&gt;cross-domain canonical&lt;/strong&gt;. When publishing on Medium, use their advanced settings to set the canonical URL to point back to your original blog post. This tells Google to give the ranking credit to your original site.&lt;/p&gt;




&lt;p&gt;Need to check if your pages are properly canonicalized? Use our free &lt;a href="https://wtkpro.site/" rel="noopener noreferrer"&gt;Canonical URL Checker&lt;/a&gt; to audit your headers and meta tags instantly →&lt;/p&gt;




&lt;h2&gt;
  
  
  External Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls" rel="noopener noreferrer"&gt;Google Search Central: Consolidate duplicate URLs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc6596" rel="noopener noreferrer"&gt;RFC 6596: The Canonical Link Relation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Abu Sufyan&lt;/strong&gt; · Full-stack developer · Founder of WebToolkit Pro&lt;br&gt;
&lt;a href="https://github.com/abusufyan-netizen" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last updated: June 2026&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://wtkpro.site/blog/canonical-url-seo-duplicate-content/" rel="noopener noreferrer"&gt;WebToolkit Pro&lt;/a&gt;. Explore our suite of 145+ free, privacy-first developer utilities at &lt;a href="https://wtkpro.site/" rel="noopener noreferrer"&gt;wtkpro.site&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>seo</category>
      <category>canonicalization</category>
      <category>duplicatecontent</category>
    </item>
    <item>
      <title>Stop Pasting JWTs Into Random Websites. Here's What I Built Instead.</title>
      <dc:creator>Abu Sufyan</dc:creator>
      <pubDate>Tue, 02 Jun 2026 06:33:44 +0000</pubDate>
      <link>https://dev.to/abusufyan909/stop-pasting-jwts-into-random-websites-heres-what-i-built-instead-159d</link>
      <guid>https://dev.to/abusufyan909/stop-pasting-jwts-into-random-websites-heres-what-i-built-instead-159d</guid>
      <description>&lt;p&gt;&lt;em&gt;By Abu Sufyan · Lead Systems Architect, WebToolkit Pro&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Every week, thousands of developers do something they know they shouldn't.&lt;/p&gt;

&lt;p&gt;They open a new browser tab, navigate to some third-party JWT decoder, and paste a live production token directly into it.&lt;/p&gt;

&lt;p&gt;That token probably contains a user ID. Maybe a role claim. Maybe an internal service identifier that maps to something sensitive in your infrastructure. And it just left your browser.&lt;/p&gt;

&lt;p&gt;I know, because I used to do it too.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Incident That Made Me Stop
&lt;/h2&gt;

&lt;p&gt;In late 2024, I was debugging an auth issue on a client's Node.js API — a financial services platform. Standard stuff: the access token wasn't refreshing correctly and I needed to inspect the payload quickly to verify the &lt;code&gt;exp&lt;/code&gt; claim.&lt;/p&gt;

&lt;p&gt;I instinctively opened a well-known JWT decoder site and pasted the token.&lt;/p&gt;

&lt;p&gt;Then I stopped.&lt;/p&gt;

&lt;p&gt;I was working in a production environment. That token belonged to a real user — a client of theirs. It contained a &lt;code&gt;sub&lt;/code&gt; (subject) claim with a UUID that mapped directly to their user database. It contained an &lt;code&gt;iat&lt;/code&gt; and &lt;code&gt;exp&lt;/code&gt;. And most critically, it contained a &lt;code&gt;roles&lt;/code&gt; claim: &lt;code&gt;["admin", "finance_read"]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I had just sent a production admin token to a third-party server I knew nothing about.&lt;/p&gt;

&lt;p&gt;The site claimed it was "client-side only." But I couldn't verify that. There was no open-source repo I could inspect. No audit trail. No CSP headers I could check. Just a text box and a promise.&lt;/p&gt;

&lt;p&gt;That afternoon, I filed an internal incident report and started building a replacement.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Makes a JWT Decoder Dangerous
&lt;/h2&gt;

&lt;p&gt;Before I get to what I built, it's worth understanding exactly why this matters technically — not just philosophically.&lt;/p&gt;

&lt;p&gt;A JWT has three parts: header, payload, and signature. The first two are just Base64url-encoded JSON. Decoding them requires zero network traffic. It's pure string manipulation you can do in two lines of JavaScript:&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.&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;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/-/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/_/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. There is no cryptographic reason a JWT decoder needs to contact any server whatsoever.&lt;/p&gt;

&lt;p&gt;And yet, when you paste a token into most online decoders, your token travels over the network to a server. That server may or may not be logging requests. It may be behind a CDN that caches POST bodies. It may be owned by a company whose threat model you have no visibility into.&lt;/p&gt;

&lt;p&gt;The attack surface is real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Session hijacking&lt;/strong&gt; if the token is still valid and the attacker can replay it against your API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claim exposure&lt;/strong&gt; — user IDs, email addresses, role names, tenant identifiers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure mapping&lt;/strong&gt; — the &lt;code&gt;iss&lt;/code&gt; (issuer) claim often reveals internal service URLs or identity provider endpoints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Algorithm fingerprinting&lt;/strong&gt; — the &lt;code&gt;alg&lt;/code&gt; header tells an attacker exactly what signing algorithm you're using, useful for crafting exploit attempts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Architecture: Zero-Knowledge Client-Side Decoding
&lt;/h2&gt;

&lt;p&gt;What I built — the &lt;a href="https://wtkpro.site/tools/jwt-decoder/" rel="noopener noreferrer"&gt;Offline JWT Decoder at WebToolkit Pro&lt;/a&gt; — operates on a simple constraint: &lt;strong&gt;nothing ever leaves the browser tab&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's the actual execution model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User pastes token → Browser JS splits on '.'
                  → atob() decodes header + payload
                  → JSON.parse() reconstructs the object
                  → Rendered directly into DOM

No fetch(). No XMLHttpRequest(). No WebSocket. No Service Worker relay.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify this yourself: open DevTools → Network tab → paste a token → watch. Zero outbound requests. The network panel stays empty.&lt;/p&gt;

&lt;p&gt;The implementation uses the Web Crypto API for signature verification — which also runs entirely in the browser sandbox. There are no API keys, no backend, no telemetry. The Content Security Policy on the page blocks outbound requests at the browser level, so even if a malicious script injection somehow occurred, it couldn't exfiltrate the token.&lt;/p&gt;




&lt;h2&gt;
  
  
  Beyond Decoding: The Signature Verification Problem
&lt;/h2&gt;

&lt;p&gt;Most online JWT decoders only decode. They don't verify.&lt;/p&gt;

&lt;p&gt;Decoding tells you what's inside the token. Verification tells you whether to trust it.&lt;/p&gt;

&lt;p&gt;The difference matters enormously in debugging scenarios. If you're diagnosing an auth failure, you need to know:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is the token malformed? (decoding fails)&lt;/li&gt;
&lt;li&gt;Is it expired? (check &lt;code&gt;exp&lt;/code&gt; vs current timestamp)&lt;/li&gt;
&lt;li&gt;Is the signature valid against the expected public key? (actual cryptographic verification)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Point 3 is where most tools fall apart. They skip it entirely, leaving you with no way to confirm whether the token was legitimately issued or tampered with.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://wtkpro.site/tools/jwt-debugger/" rel="noopener noreferrer"&gt;JWT Debugger &amp;amp; Inspector&lt;/a&gt; I built handles all three. You can paste your JWKS (JSON Web Key Set) endpoint URL or paste the raw public key directly, and the tool performs RS256/ES256 signature verification locally using &lt;code&gt;window.crypto.subtle.verify()&lt;/code&gt; — the same Web Crypto primitive your browser uses for HTTPS.&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;// What's happening under the hood&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;importKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jwk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;jwkPublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RSASSA-PKCS1-v1_5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SHA-256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;verify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RSASSA-PKCS1-v1_5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No server. No SDK. Pure browser cryptography.&lt;/p&gt;




&lt;h2&gt;
  
  
  The &lt;code&gt;alg: none&lt;/code&gt; Attack — Why Your Decoder Needs to Flag This
&lt;/h2&gt;

&lt;p&gt;While building this, I added one feature that I think every JWT tool should have: automatic detection of the &lt;code&gt;alg: none&lt;/code&gt; exploit vector.&lt;/p&gt;

&lt;p&gt;Here's the attack. Some JWT libraries — particularly older versions — accept tokens where the algorithm is set to &lt;code&gt;none&lt;/code&gt; and the signature is empty. An attacker who knows this can forge a token with any payload they want:&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;Header&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"typ"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JWT"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Payload&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1234567890"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"roles"&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="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1516239022&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Signature:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;empty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gets concatenated as &lt;code&gt;base64(header).base64(payload).&lt;/code&gt; — note the trailing dot with no signature.&lt;/p&gt;

&lt;p&gt;The decoder flags this immediately with a warning: &lt;code&gt;⚠ Algorithm "none" detected. This token carries no cryptographic integrity guarantee. Reject in production.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It's a small thing, but it's the kind of context-aware output you only get from a tool built by someone who actually works with these tokens in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned Building Privacy-First Tools
&lt;/h2&gt;

&lt;p&gt;This JWT decoder is one of 150+ tools I've built at &lt;a href="https://wtkpro.site" rel="noopener noreferrer"&gt;WebToolkit Pro&lt;/a&gt;. Every single one follows the same constraint: &lt;strong&gt;your data never leaves your browser&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Password generator. Hash generator. Base64 encoder. Regex tester. JSON formatter. AES encryption tool. All of them execute entirely client-side.&lt;/p&gt;

&lt;p&gt;Building this way taught me a few things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebAssembly changed what's possible.&lt;/strong&gt; Operations that used to require a server — like Argon2 password hashing, which is deliberately memory-intensive — can now run in the browser via WASM. The &lt;a href="https://wtkpro.site/tools/argon2-hasher/" rel="noopener noreferrer"&gt;Argon2 Hasher&lt;/a&gt; generates production-grade password hashes locally in under a second.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Workers are underused.&lt;/strong&gt; For tools that process large inputs (the JSON formatter handles payloads up to 50MB), moving the parsing off the main thread via Web Workers keeps the UI responsive. No spinners, no freezes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hardest part isn't the crypto — it's the UX.&lt;/strong&gt; Security tools have a reputation for being hostile to use. I spent more time on the output formatting and error messaging than on the underlying algorithms. A tool that correctly identifies an &lt;code&gt;exp&lt;/code&gt; claim mismatch but displays it as a raw timestamp integer has failed its user.&lt;/p&gt;




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

&lt;p&gt;If you're debugging JWTs today, open DevTools first. Network tab, record. Then go to &lt;a href="https://wtkpro.site/tools/jwt-decoder/" rel="noopener noreferrer"&gt;wtkpro.site/tools/jwt-decoder&lt;/a&gt; and paste your token.&lt;/p&gt;

&lt;p&gt;Watch the network panel stay silent.&lt;/p&gt;

&lt;p&gt;That silence is the feature.&lt;/p&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://wtkpro.site/tools/jwt-decoder/" rel="noopener noreferrer"&gt;Offline JWT Decoder&lt;/a&gt; — decode without sending tokens to any server&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wtkpro.site/tools/jwt-debugger/" rel="noopener noreferrer"&gt;JWT Debugger &amp;amp; Inspector&lt;/a&gt; — full signature verification with JWKS support&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wtkpro.site/tools/jwt-signer/" rel="noopener noreferrer"&gt;JWT Signing Tool&lt;/a&gt; — generate signed tokens locally for testing&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://wtkpro.site/tools/password-entropy-tester/" rel="noopener noreferrer"&gt;Password Entropy Tester&lt;/a&gt; — offline entropy calculation and crack time estimates&lt;/li&gt;
&lt;li&gt;Full tool directory: &lt;a href="https://wtkpro.site/tools/" rel="noopener noreferrer"&gt;wtkpro.site/tools&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Abu Sufyan is the founder of &lt;a href="https://wtkpro.site" rel="noopener noreferrer"&gt;WebToolkit Pro&lt;/a&gt; and a systems architect specializing in V8 performance, security tooling, and zero-knowledge web architectures. Find him on &lt;a href="https://github.com/abusufyan-netizen" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and &lt;a href="https://dev.to/webtoolkitpro"&gt;Dev.to&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;code&gt;security&lt;/code&gt; &lt;code&gt;jwt&lt;/code&gt; &lt;code&gt;webdev&lt;/code&gt; &lt;code&gt;javascript&lt;/code&gt; &lt;code&gt;privacy&lt;/code&gt;&lt;/p&gt;

</description>
      <category>jwt</category>
      <category>javascript</category>
      <category>security</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
