<?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: TextKit</title>
    <description>The latest articles on DEV Community by TextKit (@textkit).</description>
    <link>https://dev.to/textkit</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3807772%2F260f77ea-48fb-4755-af78-05f923f68e83.png</url>
      <title>DEV Community: TextKit</title>
      <link>https://dev.to/textkit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/textkit"/>
    <language>en</language>
    <item>
      <title>I Built 40 Free Browser-Based Tools with Flask and No JavaScript Framework</title>
      <dc:creator>TextKit</dc:creator>
      <pubDate>Sat, 07 Mar 2026 02:35:54 +0000</pubDate>
      <link>https://dev.to/textkit/i-built-37-free-browser-based-tools-with-flask-and-no-javascript-framework-4425</link>
      <guid>https://dev.to/textkit/i-built-37-free-browser-based-tools-with-flask-and-no-javascript-framework-4425</guid>
      <description>&lt;p&gt;No React. No Next.js. No build step. No node_modules.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://textkit.dev" rel="noopener noreferrer"&gt;TextKit&lt;/a&gt; — a collection of 40 free online tools for text processing, data cleaning, and developer utilities — using Flask, Tailwind CSS via CDN, and vanilla JavaScript. The entire project starts with &lt;code&gt;python app.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the stack, the architecture decisions, and what I've learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Python + Flask       → serves HTML via Jinja2 templates
Tailwind CSS CDN     → styling, zero build config
Vanilla JavaScript   → all tool logic, 100% client-side
Markdown + YAML      → blog system
Render               → hosting
Cloudflare           → DNS + caching
Umami                → privacy-friendly analytics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No database. No auth system. No npm. The entire deployment is a Flask app serving static-ish pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why no framework?
&lt;/h2&gt;

&lt;p&gt;Because these tools don't need one.&lt;/p&gt;

&lt;p&gt;A JSON formatter takes text input, calls &lt;code&gt;JSON.parse()&lt;/code&gt; and &lt;code&gt;JSON.stringify()&lt;/code&gt;, and displays the result. A password generator calls &lt;code&gt;crypto.getRandomValues()&lt;/code&gt; and builds a string. A diff checker runs an LCS algorithm on two arrays of strings.&lt;/p&gt;

&lt;p&gt;Every single tool follows the same pattern: input → transform → output. A &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;, an &lt;code&gt;addEventListener('input', ...)&lt;/code&gt;, and a function. React adds a virtual DOM, a component lifecycle, a build system, and 40KB of JavaScript to do the same thing that 20 lines of vanilla JS handles.&lt;/p&gt;

&lt;p&gt;I'm not anti-framework. I use React at work. But for this project, a framework would have been overhead with zero user benefit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Every tool is a Jinja2 template that extends &lt;code&gt;base.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;templates/
  base.html                     → nav, footer, fonts, theme CSS
  index.html                    → homepage with search + tool grid
  tools/
    json-formatter.html         → extends base.html
    password-generator.html     → extends base.html
    regex-tester.html           → extends base.html
    ... (40 tools)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Flask app is dead simple:&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="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/json-formatter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;json_formatter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;render_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tools/json-formatter.html&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One route per tool. The TOOLS registry is a list of dicts that drives the homepage grid, sitemap, and navigation. Add a tool to the list, it shows up everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  All logic is client-side
&lt;/h2&gt;

&lt;p&gt;Hard rule from day one: no text data goes to the server. Ever.&lt;/p&gt;

&lt;p&gt;Users paste sensitive stuff into text tools — API keys, database queries, internal emails, customer data. If any of that hits a server, you've created a trust and liability problem. Everything runs in the browser, and users can verify this by disconnecting from the internet — every tool still works.&lt;/p&gt;

&lt;p&gt;For most tools this is trivial. But a few pushed the limits:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diff Checker&lt;/strong&gt; — implements a full Longest Common Subsequence algorithm with character-level highlighting within changed lines. The LCS matrix is O(m×n) which means comparing two 5,000-line texts creates a 25 million cell array. Works, but I added a warning for large inputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regex Tester&lt;/strong&gt; — runs user-supplied patterns via &lt;code&gt;new RegExp()&lt;/code&gt;. Zero-length matches like &lt;code&gt;\b&lt;/code&gt; cause infinite loops in the &lt;code&gt;exec()&lt;/code&gt; loop if you don't handle them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastIndex&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// prevents infinite loop&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;CSV Parser&lt;/strong&gt; — you might think parsing CSV is &lt;code&gt;text.split(',')&lt;/code&gt;. It's not. Real-world CSV has quoted fields with commas inside, escaped quotes (double-quote within a quoted field), and newlines within quoted fields. The parser is a proper state machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time Zone Converter&lt;/strong&gt; — uses the browser's &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; API for all timezone calculations. No timezone library, no database file. Modern browsers know every IANA timezone and handle DST automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tool list
&lt;/h2&gt;

&lt;p&gt;40 tools across 9 categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delimiter tools&lt;/strong&gt; (10): Column↔Comma, Column↔Tab, Column↔Semicolon, Column↔Pipe, Column↔Space — all bidirectional&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text transform&lt;/strong&gt; (5): Case Converter, Trim Whitespace, Add Prefix/Suffix, Number Lines, Slug Generator&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data cleaning&lt;/strong&gt; (3): Remove Duplicates, Remove Blank Lines, Sort Lines&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text analysis&lt;/strong&gt; (2): Word Counter, Count Lines&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text extraction&lt;/strong&gt; (4): Extract Emails, URLs, Numbers, Phone Numbers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generators&lt;/strong&gt; (3): Password Generator, UUID Generator, Lorem Ipsum Generator&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer tools&lt;/strong&gt; (5): JSON Formatter, Regex Tester, Diff Checker, Epoch Converter, Time Zone Converter&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encode/Decode&lt;/strong&gt; (3): Base64, URL Encode/Decode, Text to Binary&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data formats&lt;/strong&gt; (2): CSV to JSON, JSON to CSV&lt;/p&gt;

&lt;h2&gt;
  
  
  SEO as architecture
&lt;/h2&gt;

&lt;p&gt;Each tool page has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unique title and meta description targeting specific search keywords&lt;/li&gt;
&lt;li&gt;200+ word "what is this tool" section&lt;/li&gt;
&lt;li&gt;FAQ section with &lt;code&gt;&amp;lt;details&amp;gt;/&amp;lt;summary&amp;gt;&lt;/code&gt; tags&lt;/li&gt;
&lt;li&gt;FAQPage schema markup (JSON-LD) — earns rich snippets in Google&lt;/li&gt;
&lt;li&gt;WebApplication schema&lt;/li&gt;
&lt;li&gt;Related tools section with internal cross-links&lt;/li&gt;
&lt;li&gt;Canonical URL and OpenGraph tags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The SEO content is roughly 70% of each page. The tool itself is a textarea and some buttons. Google ranks pages for informational queries, and the tool functionality keeps users engaged and builds backlinks organically.&lt;/p&gt;

&lt;p&gt;I also run a blog with Markdown files parsed via a simple Flask route. Each post targets a "how to" keyword and links to the relevant tool. The blog posts rank for informational queries, drive traffic, and pass internal link authority to the tool pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Build the high-traffic tools first.&lt;/strong&gt; I started with delimiter converters because they were simple. But JSON Formatter (350K monthly searches) and Password Generator (450K monthly searches) should have been first — more search volume, earlier indexing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't use Tailwind CDN in production.&lt;/strong&gt; It works and it's zero-config, but it loads the entire Tailwind stylesheet (~300KB). Self-hosting a purged CSS file would be much smaller. Haven't gotten around to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SEO content takes longer than building tools.&lt;/strong&gt; Writing the "what is" sections, FAQs, and schema markup for 40 tools took more hours than writing the JavaScript. Plan for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current status
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;40 tools live&lt;/li&gt;
&lt;li&gt;12 blog posts&lt;/li&gt;
&lt;li&gt;Indexed and ranking in Google (averaging position 20 and climbing)&lt;/li&gt;
&lt;li&gt;Thermal receipt theme — because developer tools should have personality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything is free, no accounts, no tracking. Check it out: &lt;a href="https://textkit.dev" rel="noopener noreferrer"&gt;textkit.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the stack, the SEO approach, or any of the tool implementations.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>python</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Regex Cheat Sheet: 10 Patterns That Handle 90% of Real Work</title>
      <dc:creator>TextKit</dc:creator>
      <pubDate>Thu, 05 Mar 2026 11:45:38 +0000</pubDate>
      <link>https://dev.to/textkit/regex-cheat-sheet-10-patterns-that-handle-90-of-real-work-2hfa</link>
      <guid>https://dev.to/textkit/regex-cheat-sheet-10-patterns-that-handle-90-of-real-work-2hfa</guid>
      <description>&lt;p&gt;I've been writing regex for years and I still look things up constantly. The problem with most cheat sheets is they list every possible syntax token without telling you which ones you'll actually use.&lt;/p&gt;

&lt;p&gt;Below are my working references, the patterns I reach for over and over.&lt;/p&gt;

&lt;h2&gt;
  
  
  The six characters you need to know
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\d  →  any digit (0-9)
\w  →  any word character (letter, digit, underscore)
\s  →  any whitespace (space, tab, newline)
\D  →  any NON-digit
\W  →  any NON-word character
\S  →  any NON-whitespace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uppercase = inverse. That's the whole pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quantifiers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+      one or more
*      zero or more
?      zero or one (optional)
{3}    exactly 3
{2,5}  between 2 and 5
{3,}   3 or more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;*&lt;/code&gt; vs &lt;code&gt;+&lt;/code&gt; distinction matters: &lt;code&gt;\d*&lt;/code&gt; matches an empty string (zero digits is fine). &lt;code&gt;\d+&lt;/code&gt; requires at least one digit. When in doubt, you want &lt;code&gt;+&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 10 patterns I copy-paste the most
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Email
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[\w.-]+@[\w.-]+\.\w{2,}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not RFC-perfect. Doesn't need to be. Handles real-world emails.&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;emails&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;.-&lt;/span&gt;&lt;span class="se"&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;.-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.\w{2,}&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. URLs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https?:\/\/[\w\-._~:\/?#\[\]@!$&amp;amp;'()*+,;=%]+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;s?&lt;/code&gt; makes "s" optional; it catches both http and 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urls&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;/https&lt;/span&gt;&lt;span class="se"&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;._~:&lt;/span&gt;&lt;span class="se"&gt;\/&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;amp;'()*+,;=%&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. US phone numbers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Handles &lt;code&gt;123-456-7890&lt;/code&gt;, &lt;code&gt;(123) 456-7890&lt;/code&gt;, &lt;code&gt;123.456.7890&lt;/code&gt;, and &lt;code&gt;1234567890&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. IP addresses (IPv4)
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;\b&lt;/code&gt; word boundaries are important. Without them you'd match numbers inside longer strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Dates (YYYY-MM-DD)
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;Validates format and checks month is 01-12, day is 01-31.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Hex colors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#(?:[0-9a-fA-F]{3}){1,2}\b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Matches both short &lt;code&gt;#fff&lt;/code&gt; and long &lt;code&gt;#ff00aa&lt;/code&gt; format.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Everything between double quotes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"([^"]*)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The capture group &lt;code&gt;([^"]*)&lt;/code&gt; grabs the content. &lt;code&gt;[^"]*&lt;/code&gt; means "any character except a quote, zero or more times."&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Whole word match
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\bword\b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;\b&lt;/code&gt; is the word boundary anchor. &lt;code&gt;\bcat\b&lt;/code&gt; matches "cat" but not "catch" or "concatenate".&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Numbers with optional decimals
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-?\d+\.?\d*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Matches &lt;code&gt;42&lt;/code&gt;, &lt;code&gt;3.14&lt;/code&gt;, &lt;code&gt;-7&lt;/code&gt;, &lt;code&gt;-0.5&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Multiple whitespace (for cleanup)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\s{2,}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find two or more consecutive whitespace characters. Replace with a single space.&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;clean&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;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s{2,}&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;h2&gt;
  
  
  The three mistakes I see constantly
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Not escaping periods.&lt;/strong&gt; &lt;code&gt;.&lt;/code&gt; matches ANY character. &lt;code&gt;\.&lt;/code&gt; matches an actual period. This one bites everyone at some point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Greedy vs lazy.&lt;/strong&gt; &lt;code&gt;".*"&lt;/code&gt; on the string &lt;code&gt;"hello" and "world"&lt;/code&gt; matches &lt;code&gt;"hello" and "world"&lt;/code&gt;, basically everything from first quote to last. Use &lt;code&gt;".*?"&lt;/code&gt; to match shortest: &lt;code&gt;"hello"&lt;/code&gt; and &lt;code&gt;"world"&lt;/code&gt; separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Forgetting the &lt;code&gt;g&lt;/code&gt; flag.&lt;/strong&gt; Without it, you only get the first match. Add &lt;code&gt;g&lt;/code&gt; for global.&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;// Only first match&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc 123 def 456&lt;/span&gt;&lt;span class="dl"&gt;'&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;\d&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// ["123"]&lt;/span&gt;

&lt;span class="c1"&gt;// All matches&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abc 123 def 456&lt;/span&gt;&lt;span class="dl"&gt;'&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;\d&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;// ["123", "456"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it live
&lt;/h2&gt;

&lt;p&gt;I built a &lt;a href="https://textkit.dev/regex-tester" rel="noopener noreferrer"&gt;regex tester&lt;/a&gt; with real-time match highlighting and a built-in cheat sheet. Paste a pattern, paste some text, see matches instantly. Runs in-browser, nothing stored.&lt;/p&gt;

&lt;p&gt;Full version of this cheat sheet with lookahead/lookbehind and more examples: &lt;a href="https://textkit.dev/blog/regex-cheat-sheet-beginners" rel="noopener noreferrer"&gt;textkit.dev/blog/regex-cheat-sheet-beginners&lt;/a&gt;&lt;/p&gt;

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