DEV Community

Sekhar Babu
Sekhar Babu

Posted on

I built a JSON toolkit that never sends your data anywhere

Most "paste your JSON here" tools online send that JSON to a server to
process it. For internal API responses, config files, or anything with
real data in it, that's not something I wanted to do — so I built
JSONLinter, a JSON toolkit where literally
everything happens client-side.

What it does

It started as a validator/formatter, then grew into 42 tools across six
categories:

  • Validate & Format — validation with precise error locations, pretty print, minify, JSON repair (fixes trailing commas, single quotes, unquoted keys, truncated JSON, etc.)
  • View & Query — tree view, JSONPath queries, structural diff (key order doesn't matter), full-text search
  • Data Converters — CSV, Excel, YAML, XML, SQL, Markdown, both directions
  • Code Generators — infers a type model from a JSON sample and generates TypeScript, Python, Java, C#, Go, Kotlin, Swift, Rust, or PHP
  • Schema Tools — JSON Schema validation + generation
  • Encoding Tools — Base64, escape/unescape, JWT decode

There's also an optional AI assistant on the validator page — it's
bring-your-own-key (OpenAI or Anthropic), and since there's no backend at
all, the key and your JSON go straight from your browser to the provider.
I never see either.

How it's built

Stack is React 19 + TypeScript + Vite, Tailwind v4 for styling, CodeMirror
6 for the editor. A few things I had to solve that were more interesting
than expected:

Prerendering without SSR. I didn't want to take on a Next.js-style
server just to get real HTML for crawlers. Instead, the build runs a
headless Chromium pass (Playwright) over every route after vite build
and saves the fully-rendered output to dist/<route>/index.html. Crawlers
get real content and correct per-page meta tags on first paint; once JS
loads, React takes over exactly like a normal SPA. No server, no
hydration mismatches to worry about.

Structural JSON diff. A text diff on two JSON documents is mostly
useless because key order doesn't matter semantically. The diff tool
parses both sides and compares the actual structure, so reordering keys
shows as no change, but changing a value does.

Selection highlighting, CodeMirror edge case. CodeMirror renders its
selection layer behind the text layer (z-index -2, deliberately, so
glyph rendering stays crisp), while the active-line highlight paints on
the text layer itself. If the active-line background is opaque, it
completely hides the selection highlight on whatever line your cursor is
on — which is every line right after a double-click. Fix was making the
active-line background translucent instead of a solid fill, so it blends
with the selection color underneath instead of occluding it. Took a while
to track down since "selection isn't visible" and "double-click doesn't
work" looked like different bugs at first.

Try it

It's live at jsonlinter.io — no signup, no
account, nothing to install. Would genuinely appreciate feedback, especially
on anything that feels missing compared to tools you already reach for.

Top comments (0)