<?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: frozenwindcn</title>
    <description>The latest articles on DEV Community by frozenwindcn (@frozenwindcn).</description>
    <link>https://dev.to/frozenwindcn</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%2F4107089%2F935e430b-487b-47ae-81bf-4611a55aeb8f.png</url>
      <title>DEV Community: frozenwindcn</title>
      <link>https://dev.to/frozenwindcn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/frozenwindcn"/>
    <language>en</language>
    <item>
      <title>Zero npm installs: I built a 40-page developer toolbox that loads in milliseconds</title>
      <dc:creator>frozenwindcn</dc:creator>
      <pubDate>Thu, 03 Sep 2026 02:20:34 +0000</pubDate>
      <link>https://dev.to/frozenwindcn/-zero-npm-installs-i-built-a-40-page-developer-toolbox-that-loads-in-milliseconds-4jde</link>
      <guid>https://dev.to/frozenwindcn/-zero-npm-installs-i-built-a-40-page-developer-toolbox-that-loads-in-milliseconds-4jde</guid>
      <description>&lt;p&gt;I needed to decode a JWT last week. I searched, clicked the first result, and got a login wall. The second site wanted me to "create a free account" to see my own token's payload. The third one was a 4MB React bundle that showed a spinner for three seconds before rendering a text box.&lt;/p&gt;

&lt;p&gt;So I did what developers do when annoyed enough: I built my own.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://usedevutils.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;DevUtils&lt;/strong&gt;&lt;/a&gt; is now 40 pages, 19 tools, one shared stylesheet, and &lt;strong&gt;zero npm dependencies&lt;/strong&gt;. This post is about the technical decisions that made that possible — and the ones that made it worth doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The constraint that shaped everything
&lt;/h2&gt;

&lt;p&gt;One rule, no exceptions: &lt;strong&gt;every tool runs 100% in the browser.&lt;/strong&gt; No backend, no API calls, no analytics (yet), no CDN scripts. Your data never leaves your device — and this isn't a privacy promise on a marketing page, it's verifiable: open the network tab while using any tool and watch the silence.&lt;/p&gt;

&lt;p&gt;This constraint sounds restrictive. It was actually liberating, because it eliminated entire categories of complexity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No build step. The files I edit are the files I deploy.&lt;/li&gt;
&lt;li&gt;No framework churn. No React 18 → 19 migration in my future.&lt;/li&gt;
&lt;li&gt;No supply chain. Nothing to audit, nothing to update for security patches.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The multi-page bet
&lt;/h2&gt;

&lt;p&gt;Most tool sites are single-page apps with client-side routing. I went the other way: &lt;strong&gt;one HTML file per tool&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every tool gets its own URL, which is exactly what SEO wants&lt;/li&gt;
&lt;li&gt;Each page is independently cacheable and loads in milliseconds&lt;/li&gt;
&lt;li&gt;If I break the regex tester, the JSON formatter doesn't care&lt;/li&gt;
&lt;li&gt;Deep-linking and bookmarking work the way the web intended&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole site — 40 pages — is about &lt;strong&gt;120KB zipped&lt;/strong&gt;. That's smaller than most sites' JavaScript alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  When zero dependencies means writing it yourself
&lt;/h2&gt;

&lt;p&gt;Here's where it gets fun. Three tools don't exist in the standard browser API, and I refused to pull in a library for each:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The MD5 hash generator.&lt;/strong&gt; Web Crypto gives you SHA-1 through SHA-512, but MD5 is deliberately excluded. My &lt;a href="https://usedevutils.com/hash-generator.html" rel="noopener noreferrer"&gt;hash generator&lt;/a&gt; needed it (non-adversarial checksums are still everywhere), so I implemented RFC 1321 from scratch — about 70 lines of bit-twiddling with the four-round mixing functions. Then I tested it against reference vectors: empty string, &lt;code&gt;abc&lt;/code&gt;, "message digest", Chinese text, 200-character inputs spanning block boundaries. Seven for seven against Node's &lt;code&gt;crypto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Markdown parser.&lt;/strong&gt; My &lt;a href="https://usedevutils.com/markdown-previewer.html" rel="noopener noreferrer"&gt;Markdown previewer&lt;/a&gt; needed MD→HTML conversion. Instead of loading marked or markdown-it (excellent libraries, and also two more things to load), I wrote a ~100-line parser covering the practical subset: headings, emphasis, inline code, fenced blocks, links, lists, blockquotes, tables, rules. The trick that makes it safe: escape &lt;em&gt;all&lt;/em&gt; HTML first, then apply Markdown structure — so nothing the user types can execute as markup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The CSV parser.&lt;/strong&gt; "Just split on commas" is how CSV parsers break. RFC 4180 quoting means fields can contain commas, newlines, and escaped quotes. My &lt;a href="https://usedevutils.com/csv-to-json.html" rel="noopener noreferrer"&gt;CSV to JSON converter&lt;/a&gt; implements the real state machine, so Excel exports with multi-line cells convert correctly.&lt;/p&gt;

&lt;p&gt;Was this the fastest path? No. Was it the most educational and the lightest to ship? Yes. And each hand-written piece is small enough to actually understand — the whole MD5 implementation is shorter than most dependency lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tools people actually use
&lt;/h2&gt;

&lt;p&gt;The full set covers the daily-carried utilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://usedevutils.com/json-formatter.html" rel="noopener noreferrer"&gt;JSON formatter &amp;amp; validator&lt;/a&gt; with precise error line/column&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://usedevutils.com/regex-tester.html" rel="noopener noreferrer"&gt;Regex tester&lt;/a&gt; with live highlighting and capture groups&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://usedevutils.com/jwt-decoder.html" rel="noopener noreferrer"&gt;JWT decoder&lt;/a&gt; that humanizes &lt;code&gt;exp&lt;/code&gt; claims into "VALID — expires in 47m"&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://usedevutils.com/base64.html" rel="noopener noreferrer"&gt;Base64&lt;/a&gt; that handles UTF-8 correctly (paste 你好 or emoji, no mojibake)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://usedevutils.com/timestamp.html" rel="noopener noreferrer"&gt;Unix timestamp converter&lt;/a&gt; with a live epoch clock&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://usedevutils.com/uuid-generator.html" rel="noopener noreferrer"&gt;UUID generator&lt;/a&gt;, &lt;a href="https://usedevutils.com/color-converter.html" rel="noopener noreferrer"&gt;color converter&lt;/a&gt;, &lt;a href="https://usedevutils.com/password-generator.html" rel="noopener noreferrer"&gt;password generator&lt;/a&gt;, &lt;a href="https://usedevutils.com/text-diff.html" rel="noopener noreferrer"&gt;text diff&lt;/a&gt;, &lt;a href="https://usedevutils.com/slug-generator.html" rel="noopener noreferrer"&gt;slug generator&lt;/a&gt;, &lt;a href="https://usedevutils.com/word-counter.html" rel="noopener noreferrer"&gt;word counter&lt;/a&gt;, &lt;a href="https://usedevutils.com/case-converter.html" rel="noopener noreferrer"&gt;case converter&lt;/a&gt;, and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus reference pages like a &lt;a href="https://usedevutils.com/regex-cheat-sheet.html" rel="noopener noreferrer"&gt;regex cheat sheet&lt;/a&gt;, because sometimes you don't need a tool — you need to remember what &lt;code&gt;(?&amp;lt;=...)&lt;/code&gt; does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The site is &lt;a href="https://github.com/frozenwindcn/devutils" rel="noopener noreferrer"&gt;open source (MIT)&lt;/a&gt;. Long-tail pages are generated by a Python script, so adding a tool plus its SEO variants is a config entry, not a weekend.&lt;/p&gt;

&lt;p&gt;Things I'm still figuring out: how to add analytics without violating the "your data stays with you" promise (leaning toward self-hosted, cookieless), and whether a Pro tier (bulk operations, API access) fits the no-login ethos.&lt;/p&gt;

&lt;p&gt;If you decode JWTs or format JSON as often as I do, &lt;a href="https://usedevutils.com/" rel="noopener noreferrer"&gt;give it a bookmark&lt;/a&gt;. And if you're building something with a dependency budget of zero — I'd love to hear what you had to write by hand.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Discussion prompt for the community: what's the last thing you implemented from scratch rather than importing? Was it worth it?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>sideprojects</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
