DEV Community

Solomon
Solomon

Posted on

I Built a Free Json Formatter — No Signup, No Subscription

I stopped counting how many times I opened a browser tab, pasted a blob of minified JSON into some random online formatter, and waited for it to load — only to get hit with ads, cookie banners, and a "premium" paywall after three uses. So I built something I actually wanted to use.

https://json-formatter.solomontools.workers.dev

Json Formatter takes messy, minified, or broken JSON and turns it into readable, color-coded, indented output — instantly. It validates the structure, highlights exactly where errors are, and does all of this with zero signup, zero subscription, and zero tracking. You paste; it works. That's it.

Why I Built It

The problem isn't that JSON formatters don't exist. They do. The problem is that every single one of them treats you like you're about to steal something. Pop-ups, email capture modals, "download the pro version" upsells. I wanted a tool that just... worked. No friction. No strings.

I also wanted to push my own infrastructure skills. Cloudflare Workers give you edge compute for free within generous limits, and I wanted to see if I could build a genuinely useful developer tool that runs entirely at the edge — no backend server, no database, no cold starts.

How It Works

The entire app runs on a Cloudflare Worker. When you paste JSON into the browser and hit format, a small JavaScript bundle (served from the Worker itself) parses the input, attempts JSON.parse(), and either reformats it with proper indentation or catches the error and returns a structured error message with a line and column reference.

Here's the core logic that runs on the edge:

export default {
  async fetch(request) {
    const url = new URL(request.url);
    if (url.pathname === '/api/format' && request.method === 'POST') {
      const { json } = await request.json();
      try {
        const parsed = JSON.parse(json);
        const formatted = JSON.stringify(parsed, null, 2);
        return new Response(JSON.stringify({ formatted, error: null }), {
          headers: { 'Content-Type': 'application/json' }
        });
      } catch (e) {
        // Extract line/column from the error message
        const match = e.message.match(/position (\d+)/);
        const position = match ? parseInt(match[1]) : 0;
        return new Response(JSON.stringify({ formatted: null, error: e.message, position }), {
          headers: { 'Content-Type': 'application/json' }
        });
      }
    }
    // Serve the HTML frontend for everything else
    return new Response(HTML, { headers: { 'Content-Type': 'text/html' } });
  }
};
Enter fullscreen mode Exit fullscreen mode

The frontend is a single HTML file with embedded CSS and a small vanilla JS module. No frameworks. No build step. The Worker serves both the API and the HTML — one deployment, one boundary, one thing to maintain.

Where AI comes in is in the error messages. When JSON.parse() fails, the raw error from the parser is often unhelpful — something like Unexpected token o in JSON at position 14. The Worker post-processes these messages and maps the character position back to a line and column number, then highlights the offending character in the editor. It's a lightweight heuristic, not a large language model, but it's the kind of small intelligence layer that makes a tool feel polished rather than raw.

What I Learned Shipping It

Edge compute is deceptively simple until it isn't. The first version took me about two hours to wire up. The second version took two days because I realized that serving a full HTML page from a Worker means you're responsible for everything — caching headers, content-type negotiation, handling GET vs POST, and making sure the response is fast enough that users don't perceive any lag.

Caching matters more than you think. I added a Cache-Control: public, max-age=3600 header on the HTML response. The Worker's edge network caches the page, so repeat visitors get an instant load from the nearest PoP. The API endpoint is Cache-Control: no-store since every paste is unique, but the static assets (the page shell) are cached aggressively.

Zero analytics is a feature, not a problem. I don't track visitors. I don't collect emails. I know the tool works because people use it — and I can check Cloudflare's dashboard for request volume and geographic distribution. It's enough.

The hardest part was the editor UX. Making error highlights feel responsive, keeping the textarea scroll position stable when you reformat, and handling large payloads (I cap at 1MB to protect the Worker's memory limits) all took more iteration than the actual API logic.

What's Next

I'm considering adding a few more features — JSON-to-YAML conversion, a collapse/expand tree view for nested objects, and maybe a "copy formatted" button with a toast notification instead of the browser's default alert. But the core tool is live, it's free, and it works. That's the important part.

Cost and Monetization

The tool is completely free to use. I cover the Cloudflare Workers costs myself. If you find it saves you enough time that it's worth a few dollars, you can grab a one-time $5 license on the landing page — no recurring charges, no account required. It's a thank-you, not a gate.


Enjoyed this? I build simple, powerful AI tools — try the free Text Summarizer or browse the full toolkit at Solomon Tools. No signup, no subscription.

Top comments (0)