Code Beautifier
JSON & Data

How we built a 100% client-side JSON formatter

Why Code Beautifier never uploads your JSON, how the browser-only architecture works, and what it costs to build a formatter this way.

Most online JSON formatters work the same way: you paste your JSON, the page POSTs it to a server, the server formats it, and the result comes back. It works. It is also, for a lot of the JSON developers actually handle, a bad trade.

The payloads people paste into a formatter are rarely synthetic. They are production API responses, webhook bodies, exported customer records, config files with credentials still in them. Sending that to a third-party server to add some whitespace is a strange thing to do, and most sites do not tell you either way.

Code Beautifier does not have that server. Here is how it works instead, and what it cost to build.

Everything runs in the browser tab

The entire transform pipeline is client-side JavaScript. When you paste JSON and hit format, this is the whole path:

  1. The text goes into a CodeMirror 6 editor instance in your tab.
  2. A formatter module gets dynamically imported, if it has not been already.
  3. JSON.parse and JSON.stringify run on your machine.
  4. The result renders back into the output pane.

No network request happens at any point in that sequence. You can verify this yourself: open DevTools, switch to the Network tab, and format something. The panel stays empty.

The architecture that makes it possible

Three decisions make a no-server design practical rather than merely aspirational.

Static export. The site is a Next.js static export. There is no application server to send anything to, because there is no application server at all. The output is a folder of HTML, CSS, and JavaScript served from Cloudflare's edge. This is not a privacy feature bolted on afterward; it is a consequence of the build target.

Lazy-loaded formatters. A catalog this size means a lot of parsing libraries. Loading all of them on every page would make the site slower than the ad-heavy alternatives it exists to replace. Instead each tool's formatter is a dynamic import that only loads when you actually use that tool. The JSON page never downloads the SQL parser.

Web Workers for large payloads. Formatting a 5 MB file on the main thread janks the entire tab. Above a size threshold, the work moves to a Web Worker so the UI stays responsive. The workers are split by family (JSON, markup, encoding) so you only download the one your tool needs.

What this costs

Being honest about the tradeoffs, because there are real ones:

Some things are impossible. Server-side formatters for Python, Rust, or Java would require running those toolchains somewhere. We do not, so those tools do not exist here. A site with a backend can offer them; we cannot without breaking the one promise that matters.

Bundle size is a constant fight. Every formatting library ships to the browser instead of living on a server. That is why the lazy loading and the worker splitting are not optimizations we got around to, they are load-bearing. The markup worker is currently around 557 KB, which is larger than we want it.

Very large files hit browser limits. There is a ceiling on what a tab can hold in memory. A server would not have that constraint in the same way.

We think these are the right trades. A formatter that is slightly more limited but never sees your data is more useful than a comprehensive one you cannot paste a production token into.

Verify it yourself

You do not have to take any of this on faith, which is the point:

  • Watch the network tab. Format something and confirm nothing leaves.
  • Go offline. Open a tool once, then turn off your wifi. It keeps working, which is only possible if the work was local all along.

The JSON Formatter is the best place to start. Paste something you would not paste anywhere else.