DEV Community

ke jia
ke jia

Posted on

14 DevTools, Zero npm Packages: Why I Ship Pure HTML Instead of JavaScript

I recently shipped a collection of 14 developer tools. A Cron parser, a JWT decoder, a Base64 encoder, a Diff tool, a QR code generator, and a dozen more. They're all useful, all client-side, and all instantly available in a browser tab.

Here's the part that surprises people: none of them have a package.json.

No npm install. No build step. No node_modules folder. No bundler. No framework. Each tool is a single HTML file you can open directly, host on any static server, or even email to a coworker.

This post is a comparison. I'll lay out the two approaches side by side — the "default" npm/JavaScript way and the pure-HTML way — and show you exactly where each one wins. Because the honest answer is that pure HTML is not always the right choice. I'll tell you when it is, and when you should absolutely reach for npm instead.

The default way, and why it feels heavy

If you asked most developers to build a "generate a UUID" tool, the path of least resistance looks like this:

npm create vite@latest uuid-tool
cd uuid-tool
npm install
npm install uuid
npm run dev
Enter fullscreen mode Exit fullscreen mode

You now have a project. A package.json. A vite.config.js. A node_modules folder with a few hundred transitive dependencies. A build pipeline. And a tool that does one thing: print a random UUID.

None of that is wrong. For a real product, a real app, a real codebase that a team maintains, the npm ecosystem is a superpower. The problem is that the default has become so automatic that we reach for it even when the task is a 40-line utility that will never change.

For a one-off tool, that's a lot of machinery to spin up just to print a string.

What the collection actually is

Before the comparison, here's what we're comparing. The developer toolbox is 14 tools, each a self-contained HTML page:

Tool What it does
Cron Expression Parser Parse and visualize cron expressions (second/minute/hour/day/month/week)
YAML to JSON Convert between YAML and JSON with live preview
URL Slug Generator Turn titles into URL-friendly slugs, multilingual
HTML to Text Strip HTML down to clean text
QR Code Generator Generate QR codes for URLs, text, contacts
HTML Entities Encoder/Decoder Encode/decode special characters to entities
UUID Generator RFC 4122 v4 UUIDs, batch generation, format conversion
Password Generator Strong passwords with custom length and character sets
Lorem Ipsum Generator Placeholder text by paragraph/sentence/word
Hash Generator SHA-1/256/384/512 for text and files
Base64 Encoder/Decoder Text and file Base64, URL-safe mode
JWT Decoder Decode and inspect JSON Web Tokens
Diff Tool Side-by-side text diff with added/removed/changed highlighting
CSV to JSON Convert between CSV and JSON with live preview

Every single one of these runs entirely in the browser. Your data never leaves the page. There's no backend, no API key, no "upload to our server" step. That last point matters more than it sounds, and I'll come back to it.

The comparison: pure HTML vs. npm

Let's go category by category. I'll be honest about where npm wins, because a comparison that only shows one side isn't a comparison.

1. Setup and distribution

npm: You need Node installed, you run npm install, you run a build, and you deploy the output. To use the tool, someone has to run your build or you have to host the built assets.

Pure HTML: The file is the distribution. You open it. You're done. You can host it on GitHub Pages, Netlify, S3, a company intranet, or literally send the .html file over Slack. There is no "how do I run this?" question.

Winner: Pure HTML, by a wide margin, for tools.

2. Build step

npm: A build step means a build config, a bundler, and the inevitable "it works on my machine but not in CI" debugging. It also means your source and your artifact are two different things that can drift apart.

Pure HTML: No build. What you write is what runs. There's nothing to misconfigure.

Winner: Pure HTML.

3. Dependencies and supply chain

This is the big one, and it's the reason I care about this so much.

npm: Every npm install pulls in a tree of transitive dependencies. Every one of those is a potential supply-chain risk. A compromised package, a malicious postinstall script, a typosquatted name — the npm ecosystem has seen all of it. When you depend on 300 packages to generate a UUID, you've accepted 300 chances for something to go wrong, most of which you've never read the source of.

Pure HTML: Zero dependencies. The only code running is the code you wrote and can read in its entirety. There is no node_modules to audit, no lockfile to trust, no transitive package you've never seen. The attack surface is the file itself, and the file is small enough to actually review.

Winner: Pure HTML, and this is the one I'd weight most heavily.

4. Offline and air-gapped use

npm: A built app can run offline, sure. But building it requires the network and the registry. And if you're in an air-gapped environment, getting the dependencies in is a real chore.

Pure HTML: The file works with no network at all. Open it on a machine with no internet and it just works. For teams in restricted environments, that's not a nice-to-have, it's the whole point.

Winner: Pure HTML.

5. Startup and performance

npm: A bundled SPA has to download and parse JavaScript before it can do anything. For a tool that does one thing, that's overhead you pay on every load.

Pure HTML: The page is small. It loads fast. There's no framework to hydrate, no bundle to parse. For a utility, the "app" is ready the moment the file finishes loading.

Winner: Pure HTML for small tools. (For a large, complex app, a well-optimized bundle can beat a hand-rolled page — but that's not what we're building here.)

6. Where npm genuinely wins

Now the honest part. Pure HTML is not a universal answer. npm is the right choice when:

  • You need a real library. If your tool needs a mature parser, a charting engine, or a crypto library with a track record, you want the battle-tested npm package, not a 200-line reimplementation you have to maintain forever.
  • You're building a product, not a tool. If this is going to be a maintained product with a team, tests, CI, and a release process, the npm ecosystem's tooling is a feature, not a burden.
  • You need to share code across projects. If the same logic lives in five places, a package with a version and a changelog beats copy-pasting HTML.
  • You need the ecosystem's edge cases handled. Date handling, internationalization, accessibility — the npm packages have had years of edge cases fixed by other people.

The rule I use: if the tool is small, stable, and single-purpose, pure HTML. If it's growing, shared, or complex, npm.

How I actually build these

For the curious: each tool is one HTML file with inline CSS and inline JavaScript. No framework, no transpiler. A few notes on the interesting bits:

  • Hashing and UUIDs use the browser's built-in Web Crypto API (crypto.subtle.digest, crypto.randomUUID). No external crypto library needed — the browser already ships a vetted implementation.
  • File handling (Hash, Base64) uses the FileReader API. Files are read locally and processed in the page. Nothing is uploaded.
  • The Diff tool implements a simple line-based diff in vanilla JS. It's not a full Myers diff, but for the "compare two config files" use case it's plenty, and it's 100% readable.
  • YAML/CSV parsing are small, focused parsers written for the specific shapes these tools need. They're not general-purpose YAML engines, and that's intentional — they do one job and are easy to verify.

The constraint of "no dependencies" is actually a design constraint, not just a technical one. It forces you to keep each tool small and focused. If a tool starts needing a real library, that's a signal it's outgrown the pure-HTML model — and that's fine, that's when you graduate it to npm.

The security angle (why "client-side" is a feature)

I keep coming back to this, so let me be explicit. A lot of "free online tools" work by sending your data to a server. You paste your JWT, your CSV, your config, and it goes to their machine. For a JWT decoder or a CSV converter, that means your secrets and your data are now in someone else's logs.

The pure-HTML approach sidesteps this entirely. Because there's no backend, your data never leaves your browser. The JWT you decode, the CSV you convert, the text you hash — it's processed locally and gone. For tools that touch sensitive data, "it runs in your browser" isn't a marketing line, it's the actual security model.

Combine that with zero dependencies (no supply-chain risk) and you get a tool that's safe in two different ways: it doesn't leak your data, and it doesn't pull in untrusted code.

When I'd reach for npm instead

To be concrete, here are the tools in this collection that I wouldn't have built in pure HTML if they were bigger:

  • A full-featured YAML editor with schema validation and autocomplete would need a real YAML library and a code editor component. That's npm territory.
  • A charting tool would want a maintained charting library, not a hand-rolled canvas renderer.
  • A large-file diff with merge capabilities would want a serious diff engine.

The 14 tools here are all deliberately in the "small and stable" zone. That's the zone where pure HTML wins. The moment a tool leaves that zone, I'd graduate it to a proper npm project without hesitation.

Try it

The collection is live at wuchunjie00.github.io/devtools, and the source is on GitHub. Every tool is a single HTML file you can read in full. If you're curious how a JWT decoder or a Diff tool works without a single dependency, the source is the best documentation — it's short enough to actually read.

The takeaway

The npm ecosystem is one of the best things that ever happened to JavaScript, and for real products it's irreplaceable. But the default has become so automatic that we spin up a build pipeline to print a UUID.

For small, stable, single-purpose tools, there's a lighter path: pure HTML, zero dependencies, runs in the browser, data never leaves the page. It's faster to ship, safer to run, and easier to trust — because the entire codebase is one file you can read in ten minutes.

Use npm when you're building a product. Use pure HTML when you're building a tool. And the next time you're about to npm create a project that's really just a converter, ask yourself: does this actually need a node_modules folder?

Sometimes the most modern thing you can do is write a single HTML file.

Top comments (0)