Working with JSON every day, I found myself constantly switching between browser tabs to format messy payloads from APIs. Every tool I used either had ads everywhere, required signup, or sent my data to a server. So I built my own.
jsonproject.com — a free, browser-only JSON formatter, validator, and auto-fixer. No ads, no signup, no data ever leaves your machine.
What it does
- Format & pretty-print — 2, 3, 4 spaces, tabs, or compact mode
- Validate against RFC 8259 with inline error markers
- Minify for production payloads
- Auto-fix broken JSON — trailing commas, single quotes, unquoted keys
- Fetch JSON from a URL — paste an API endpoint and format the response instantly
- Drag-and-drop file upload
- Format history — last 20 operations saved in session
- Dark mode
- Monaco Editor — same editor as VS Code, with full syntax highlighting
Tech stack
- Angular 21 with SSR and prerendering
-
Monaco Editor via
ngx-monaco-editor-v2 - Tailwind CSS for styling
- TypeScript throughout
The interesting parts
Monaco Editor in Angular SSR
The trickiest part was getting Monaco Editor to work with Angular's server-side rendering. Monaco is a browser-only library — it directly accesses window, document, and the DOM. Running it on the server causes everything to crash.
The fix: wrap the entire formatter component with ngSkipHydration and guard all Monaco initialization behind isPlatformBrowser():
if (isPlatformBrowser(this.platformId)) {
// Monaco-specific code here
}
And in the template:
<app-formatter ngSkipHydration></app-formatter>
This lets Angular prerender the shell HTML on the server while Monaco initializes fully on the client.
Auto-fix engine
The auto-fixer handles the most common JSON mistakes developers make:
private attemptFix(input: string): string {
let s = input.trim();
// Remove trailing commas before } or ]
s = s.replace(/,(\s*[}\]])/g, '$1');
// Convert single quotes to double quotes
s = s.replace(/'([^']*)'(\s*:)/g, '"$1"$2');
s = s.replace(/:\s*'([^']*)'/g, ': "$1"');
// Quote unquoted keys
s = s.replace(/([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)(\s*:)/g, '$1"$2"$3');
return s;
}
It's not a full parser — it uses targeted regex passes to handle the 90% case without breaking valid JSON.
Equal editor heights
A subtle UX detail: making the input and output Monaco editors show exactly the same number of lines. Both use the same clamp height:
height: clamp(240px, 42vh, 490px)
And critically — never use flex-1 on a Monaco editor. It sets flex-basis: 0 which overrides the explicit height and causes the editor to collapse on mobile.
Privacy
All JSON processing is 100% client-side. The app is prerendered static HTML served from Hostinger. No backend, no database, no analytics on the JSON content. Google Analytics only tracks page views.
Try it
jsonproject.com — free, no signup, works on mobile too.
Would love feedback — what features would you add? Drop a comment below.
Top comments (0)