DEV Community

Rupesh Jadhav
Rupesh Jadhav

Posted on

I built 10 free dev & QA tools that run in your browser, then tested them like production

I've spent 20+ years in QA, and a surprising amount of my day goes to small chores: generating test data, pretty-printing an API response, diffing two payloads, checking a YAML pipeline file before it breaks a build.

For years I used a dozen different websites for those chores. Some were full of pop-ups, some wanted a sign-up, and many sent whatever I pasted to their server. That last part never sat well with me, because what testers paste is often a real API response, a token or a config file.

So I built my own: My Toolbox (rj-toolkit.com), ten free tools in one place that run entirely in your browser. And because I'm a tester, I couldn't stop at building it. I tested it the way I'd test a production app, and it had real bugs. More on that below.

What's inside

No sign-up, no limits.

Why it all runs in the browser

There's no backend. Every conversion, format and check happens in JavaScript on your machine, and nothing you paste is uploaded or stored. You can confirm it yourself: open DevTools, switch to the Network tab and use any tool. Your input never shows up in a request.

For testers this matters more than it seems. The data we handle every day, such as API responses, JWTs, connection strings and customer-like records, is exactly the data you shouldn't paste into a random server. It also keeps the site fast and cheap to run: it's static files on shared hosting.

Testing my own side project like production

It's easy to ship a side project because "it works on my machine". I wrote a proper test plan instead: unit, end-to-end and non-functional checks, with a risk-based priority for each case. The first code review against that plan found four real bugs.

1. The JSON tool executed whatever you pasted. To turn a JavaScript object like {name: 'Ana'} into JSON, the Stringify button did this:

const parsedObj = (new Function('return ' + input))();
Enter fullscreen mode Exit fullscreen mode

That runs any JavaScript in the page. Paste alert(document.domain) and it fires. It's "only" self-XSS today, but the moment someone adds a shareable link that pre-fills the input, it becomes a real vulnerability. I replaced it with a small parser for object and array literals that never executes anything. It still accepts unquoted keys, single quotes, comments and trailing commas, and it rejects functions, variables and ${} templates.

2. The "secure" password generator wasn't. It used Math.random(), which is not cryptographically secure. It now uses crypto.getRandomValues() with rejection sampling so every character is equally likely. It also guarantees at least one character from each set you choose. Unit tests now cover the length, the character sets and the error when no set is chosen.

3. SQL minify could break your query. Minifying puts the query on one line, so a -- comment silently commented out everything after it, and spaces inside 'quoted strings' got collapsed. That means changed data. Line comments now become /* */ comments, and quoted text is left alone.

4. camelCase kept hyphens. hello-world_value came out as hello-World_value. Small, but it's a naming tool, so getting names wrong is the whole job.

None of these showed up in normal clicking around. All four were found by asking "what's the worst input someone could give this?", which is the habit I'd want any tester to bring to a project.

The stack and the pipeline

  • React 19 + TypeScript + Vite. Each tool is lazy-loaded as its own chunk. The first version shipped one 3.9 MB bundle with every library in it; now the main bundle is about 225 KB and heavy libraries like Terser and sql-formatter load only on the page that uses them.
  • Shared logic in plain TypeScript modules, separate from the React components, so it can be unit-tested directly.
  • Vitest for unit tests of that logic, including every pair of the data converter's formats.
  • Playwright end-to-end tests on desktop Chrome and a Pixel 7 viewport: every tool opens without console errors, the converter runs all 25 input/output format pairs through the real UI, and each tool page is checked for its own title, H1, canonical URL and structured data.
  • GitHub Actions: every pull request runs typecheck, unit and browser tests. Merging to main waits for my manual approval, then builds the site and pushes only the built files to a deploy branch.
  • Hostinger shared hosting pulls the deploy branch with Git auto-deployment. The pipeline then waits until the live site serves the new build and runs the @live-tagged smoke tests against production.

That last step is my favourite part. A deploy isn't "done" when the files are uploaded; it's done when the live site passes its tests.

One lesson about single-page apps and search

The first version was a classic single-page app: one URL, an empty <div id="root">, and all ten tools behind tab buttons. To a search engine that's one nearly blank page.

The fix didn't need a framework change. A small Node script runs after vite build and writes a real HTML page for each tool, like /json-formatter/. Each page has its own title, description, canonical URL, structured data, H1, how-to steps and FAQ, all in the HTML before any JavaScript runs. React still renders the interactive tool on top. One JSON file holds the page text for both the app and the build script, so they can't drift apart.

What's next

I'm deciding what to add next, and I'd like your input:

  • What small tool do you keep searching the web for?
  • Anything in the current tools that's missing or annoying?
  • Found a bug? I'd genuinely like to hear about it. Breaking things is my day job, so I'll take it as a compliment.

Try it at rj-toolkit.com and tell me in the comments. Thanks for reading!

Top comments (0)