Open-source project
triggerdotdev/jsonhero-web avatar
triggerdotdev/jsonhero-web

JSON Hero: a self-hostable JSON viewer whose only API calls itself unofficial

Project brief: JSON Hero is an open-source, beautiful JSON explorer for the web that lets you browse, search and navigate your JSON files at speed. . Built with by the Trigger.dev team.

10,892 stars668 forksTypeScriptApache-2.0

At a glance

What is it?
JSON Hero is a TypeScript web app for browsing JSON, built by the Trigger.dev team on Remix and Cloudflare Workers, shipped as source rather than a package. Its real limits are the hosted-service dependency, the Base64-in-URL sharing form, and a Dockerfile that bakes a placeholder session secret into the image.
Who is it for?
JSON Hero is a good fit for a team that wants to self-host a JSON browser and is willing to own the deployment, and a poor fit for anyone who needs a versioned API or a hard retention guarantee on hosted documents.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 11 months ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • triggerdotdev/jsonhero-web10,892 ★ · +105
Star history
Repository2026-08-042026-11-13
triggerdotdev/jsonhero-web10.8k10.9k

105 Stars in the last 101 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The documented entry point is jsonhero.io, and the API is labeled unofficial

JSON Hero is a web application, not a library. The repository has no GitHub releases, and the described routes all point at the hosted site: drag and drop a file at jsonhero.io, or paste JSON or a JSON URL into the form there. The single programmatic route is the one the README calls the unofficial API, a POST to jsonhero.io/api/create.json. Its response carries three fields, an id, a title, and a location URL of the shape https://jsonhero.io/j/YKKduNySH7Ub. Underneath, the app is Remix on Cloudflare Workers, with remix.config.js, a wrangler.toml, a worker/ directory and an entry.worker.ts search bundle. The consequence for a reader is that anything built on that endpoint sits on a surface its own documentation declines to call stable.

A ttl field can expire your document, and no default is documented

The create.json body accepts two optional switches. readOnly, when true, will make it so the document title cannot be edited or the document cannot be deleted. ttl takes a number of seconds and will expire the document after 3600 seconds in the example given. Both are marked optional, and neither has a stated default in the README, so a caller who omits ttl has no documented statement of how long the payload survives. The consequence for a reader is the direct one: this endpoint posts your JSON to a host you do not operate. Leaving ttl unset does not mean you chose an expiry, it means the expiry is unspecified. Sensitive payloads do not belong on that endpoint, and the top-level SELF_HOSTING.md file is where the self-hosted path begins.

Two sharing forms carry the document or the fetch inside the URL

Both share links put something in the address itself. The first appends a Base64 encoded string of a JSON payload to the new endpoint, for example jsonhero.io/new?j=eyAiZm9vIjogImJhciIgfQ==. The second appends a JSON URL, for example jsonhero.io/new?url=https://jsonplaceholder.typicode.com/todos/1. The Base64 form is a convenient way to hand someone a document by link, but the document is in the URL, so it lives in browser history and can reach request logs on the way. The url form asks jsonhero.io to fetch an address you supply, so the viewer performs an outbound request to whatever host you name. Neither form is authenticated, and no size limit, retention rule or expiry is documented for either one.

Search is an esbuild artifact that remix build never produces

The build script is a chain. npm run build runs build:css, then build:search, then remix build. build:search is an esbuild call bundling ./app/entry.worker.ts into ./public/entry.worker.js with --format=esm, and build:css runs tailwindcss from ./styles/tailwind.css into ./app/tailwind.css. The search worker is therefore a separate artifact from the Remix output, and a build that invokes remix build on its own yields an app with no search bundle in place. The development path mirrors the split: npm run dev runs three concurrent watchers, dev:css, dev:search and remix watch, with dev:search writing the same worker file under a development define rather than a production one. The consequence is that public/entry.worker.js is generated output, and editing it by hand gets overwritten on the next watch cycle.

A private package means the editor extensions are separate problems

package.json carries "private": true and names the project @jsonhero/jsonhero-web, so the npm publish path is closed and that name exists only inside this repository. That is consistent with a self-hostable web app, but the cost lands on whoever forks it. Alongside app/, worker/, public/ and styles/, the tree carries tests/, an examples/ directory holding owenWilsonWows.json, pokemon.json and ronSwansonQuotes.json, and three deployment shapes: wrangler.toml, wrangler.toml.dev and a Dockerfile. The two editor integrations the README points at, the VS Code extension and the Raycast extension, are separate projects outside this repository. A reader gets the web app and nothing else, so any editor integration can change on its own schedule with nothing in this tree coordinating it.

The Dockerfile writes SESSION_SECRET=abc123 into a committed layer

The Dockerfile is a single stage built FROM node:16.17.0 as builder. It copies the whole source into /src, runs npm install, then runs RUN echo "SESSION_SECRET=abc123" > .env, and closes with RUN npm run build and CMD npm start. Two consequences follow. The string abc123 is the same placeholder the README hands local developers, and after a docker build it sits in a layer of the resulting image, readable by anyone who pulls that image or pushes it to a registry. Because the stage is single, the shipped image carries the source tree and the build toolchain rather than only the built output. Do not put a real secret into the Dockerfile or image layers. Before deploying, remove the baked-in placeholder and configure a unique random secret at runtime using a protected secret mechanism compatible with your deployment; verify how the application loads it. Treat node:16.17.0 as the runtime version everything else inherits.

One secret and one port stand between a clone and a running viewer

The local path is a clone, an install, one secret and a port. To run locally, first clone the repo and install the dependencies:

bash
git clone https://github.com/triggerdotdev/jsonhero-web.git
cd jsonhero-web
npm install

Then create a `.env` file at the root with a unique, cryptographically random `SESSION_SECRET`. The upstream example `abc123` is a public placeholder and must not be used for a deployment. Keep the file private and out of version control.

Then, run `npm run build` or `npm run dev` to build.

Now, run `npm start` and open your browser to `http://localhost:8787`. The install step also triggers a postinstall script, remix setup cloudflare-workers. There is no configuration wizard and no other documented setting. The consequence for a reader is that the one secret in this project is a single string with a placeholder value, and nothing warns you that the placeholder is still in place.

npm start runs watchers under a Workers emulator, not a fixed server

The documented start command resolves to a concurrent pair. npm run dev is itself the three watchers described above, and npm run start:worker runs miniflare --env .env --build-command "npm run dev:worker" --watch. miniflare is a local Workers emulator, so the local run and the deployed run are not the same runtime. The Dockerfile uses npm start as its command, so that watcher pipeline is also the image default. Actual deployment is a different script: npm run deploy runs npm run build and then wrangler publish, and npm run deploy:production adds --env production. The local walkthrough ends at opening http://localhost:8787 and never documents a production start command, so the README gives a self-hosted copy outside Cloudflare no documented entry point.

Editorial conclusion

JSON Hero is a good fit for a team that wants to self-host a JSON browser and is willing to own the deployment, and a poor fit for anyone who needs a versioned API or a hard retention guarantee on hosted documents. Before you commit, check three things: replace the SESSION_SECRET placeholder baked into the Dockerfile, check SELF_HOSTING.md for self-hosting guidance, since the README never documents a production start command, and decide up front whether your payloads may sit on jsonhero.io with no stated expiry.

Frequently asked questions

How to open a .JSON file online?

Head to jsonhero.io and drag and drop a JSON file into the page, or paste JSON or a JSON URL into the form provided there. There is also a VS Code extension and a Raycast extension that open JSON in the viewer.

What is a Json Viewer used for?

JSON Hero offers Column View, Tree View and Editor View, fuzzy search across key names, key paths and values, inferred previews for strings, related values for a field including undefined and null, and an inferred JSON Schema that could be used to validate your JSON.

What content previews does JSON Hero provide?

JSON Hero is built around reading one: it infers the contents of strings into previews for dates, image URLs, website URLs, tweet URLs, JSON URLs and colors, and it surfaces related values across the document so you can check for edge cases.

What is the stated goal of JSON Hero?

The project's stated goal is making reading and understanding JSON files easy by giving you a clean interface packed with extra features, including keyboard navigation, a path bar, history in Column View, and easily sharable URLs with path support.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/triggerdotdev-jsonhero-web.svg)](https://hysenlabs.com/projects/triggerdotdev-jsonhero-web)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/triggerdotdev-jsonhero-web.svg)](https://hysenlabs.com/projects/triggerdotdev-jsonhero-web)

Was this useful?