Skip to content
Marvin's Toolbox.

Search tools

Type to filter all tools

Technical overview

How marvins.tools works

A look under the hood: what a tool actually is, how tools pass results to each other, and how a website can process your files without ever seeing them.

The short version

Almost everything interesting about this site is what it doesn’t have. There’s no backend doing the work, no database holding your files, and no upload endpoint waiting for your data. The server hands your browser a page and some JavaScript, and from that moment on, your machine does all the work.

That one decision shapes everything else on this page. It’s why the tools are fast, why they keep working on a flaky connection, and why the privacy promise isn’t a policy but a property of the architecture. You don’t have to take my word for it, you can open your browser’s network tab and watch it stay quiet while you work.

What a tool actually is

A tool here is one page that does one job. A compressor, a converter, a calculator. Under the hood, each one is just two things: a React component with the actual logic, and a small metadata entry in a central registry.

The registry entry describes the tool. Its URL slug, name, description, category, tags, icon, and a declaration of what kinds of data it consumes and produces. That single list drives the whole site. The search index, the category and tag pages, the sitemap, the structured data for search engines and the cross-tool suggestions are all generated from it.

There are no per-tool route files either. One dynamic route looks up whichever tool the URL names and renders it. Adding a new tool means writing the component and one registry entry, and the rest of the site picks it up automatically.

Your browser does the heavy lifting

When you drop a file into a tool, the browser opens it locally with the File API. Nothing is uploaded, because there is nowhere to upload it to. What happens next depends on the job:

  • Images are decoded and re-encoded with the canvas API. The heavy work runs in Web Workers, so the page stays responsive while a large photo is being compressed or converted.
  • Hashing runs on WebAssembly. Compiled hash functions get close to native speed, which matters when you’re checksumming a big file.
  • Compression uses the browser’s built-in CompressionStream for gzip and deflate, plus WebAssembly builds of Brotli and Zstandard for the formats browsers don’t ship.
  • Text and data tools are plain TypeScript. Parsing JSON, diffing text or decoding a timestamp doesn’t need anything fancier.

A nice side effect: there are no file size limits, no queues and no processing quotas. The only limit is what your machine can handle.

How your work is saved

Tools remember your work between visits, and that memory also lives on your device. A tool’s current state is autosaved to the browser’s local storage under a key derived from the tool’s slug, so no tool can ever read another tool’s data.

Every saved state is wrapped in a versioned envelope. When an update changes the shape of a tool’s state, small migration steps upgrade old data as it loads, so a save from months ago still opens fine today.

Many tools also let you keep named snapshots, and there’s a safety net on top. Whenever something replaces your current work, like opening a snapshot or a share link, the replaced state is set aside for a day. One click brings it back.

Tools that talk to each other

Every tool can declare what it consumes and produces using MIME-like types, such as image/png or text/plain. Consumers can accept whole families with wildcards like image/*. A small matching engine compares each tool’s outputs against every other tool’s inputs, and the matches become the "Next steps" cards you see after producing a result.

Clicking a card hands your result to the next tool over two transport layers. An in-memory slot covers the normal case of client-side navigation and passes files by reference, with no copying and no size limit. An IndexedDB copy backs it up, so the handoff also survives a full page load or opening the tool in a new tab. Delivery happens exactly once, and an unclaimed handoff expires after ten minutes.

If the receiving tool doesn’t accept the exact format, a conversion table can re-encode the data on the way. A PNG result can flow into a tool that only takes JPEG without you ever thinking about formats.

Share links without a server

Some tools can turn your current state into a link you can send to someone. The state is serialized to JSON, compressed with deflate, encoded as base64url and placed in the URL after a # character.

That fragment is the trick. Browsers never send the part after # to any server, so the content of a share link travels only from you to whoever you send it to. Opening the link runs the same steps in reverse, and the recipient’s browser validates and decompresses the payload locally. A damaged or tampered link simply does nothing.

The stack

For the curious, the main ingredients:

  • Next.js (App Router) with React and TypeScript. Server components handle routing, metadata and structured data, and the tools themselves are client components.
  • Tailwind CSS and shadcn/ui for the interface.
  • CodeMirror for the code and text editors.
  • WebAssembly modules for hashing and the compression formats browsers don’t provide.
  • Vercel for hosting the static pages and the tiny bit of server code that is needed to serve the site.

Analytics are cookieless and anonymous. They count page views so I can see which tools people actually use, and that is all they do.

Keeping it honest

A site full of calculators and converters is only useful if the results are right. Every change runs through thousands of unit tests before it deploys, checking the tools’ logic against known inputs and edge cases.

On top of that, contract tests enforce the site’s own rules. Every tool must ship its own written content. Every declared input must actually be wired up to receive data, and every declared output must actually be offered for forwarding. Every curated recommendation must point at a tool that can really accept the data it would be sent.

That’s the whole system

A registry, a pile of small client-side pages, some modern browser APIs doing work that used to need a server, and a test suite keeping everything honest. It stays fun to build precisely because it is small, and new tools get added whenever an everyday task turns out to be annoying enough to deserve one.

Browse the tools

Last updated: 4 July 2026