close

DEV Community

Cover image for I Built 30 Free Developer Tools with Next.js and FastAPI — Here's How
Jordan
Jordan

Posted on

I Built 30 Free Developer Tools with Next.js and FastAPI — Here's How

The problem with developer tools online

Every developer has a graveyard of bookmarks. One site for JSON formatting, another for JWT decoding, another for regex testing. Some require you to create an account just to paste some text. A few are so slow you've already given up and written a one-liner in the terminal by the time the page loads.

The worst part is the data question. Paste a JWT from a staging environment into some random site and you have no idea what's happening on the other end. Most of these tools don't tell you. Some of them are definitely logging it.

I got tired of it. So I built one place with all the tools I actually use, where nothing leaves your browser. No sign-up, no server processing your data. Just paste, transform, copy, and move on.

What Dev-Toolbox is

dev-toolbox.io is a collection of 30+ free browser-based developer utilities organized into six categories:

  • Formatters — JSON, HTML, CSS, JS, SQL, XML
  • Encoders / Decoders — Base64, JWT, URL
  • Validators — Regex Tester, JSON Schema, Cron Parser, JSONPath Tester
  • Converters — Color, JSON to CSV, JSON to YAML, Markdown to HTML, Timestamp, Number Base
  • Generators — UUID, Hash, Password, Lorem Ipsum, Slug
  • Minifiers — HTML, CSS, JS

The architecture decision

The core decision I made early on was this: the backend does not touch tool data. Ever.

All 30 tools run entirely in the browser. The JSON formatter formats JSON in the browser. The regex tester tests regex in the browser. Nothing gets sent to a server for processing. This isn't just a privacy feature — it also makes the tools instant. There's no round-trip. You type and it responds.

The frontend is built with Next.js. The reason is straightforward — Next.js gives you static site generation per page out of the box, which means every tool page is pre-rendered at build time.

Here's what a tool engine component looks like at its simplest:


// ToolPageLayout lazy-loads the right engine by componentKey
const componentMap: Record<string, ComponentType> = {
  JsonFormatter: dynamic(() => import("@/components/Tools/engines/JsonFormatter")),
  RegexTester:   dynamic(() => import("@/components/Tools/engines/RegexTester")),
  JwtDecoder:    dynamic(() => import("@/components/Tools/engines/JwtDecoder")),
  // ... 27 more
};


// Each engine receives shared state from the layout
<ToolEngine
  activeAction={activeAction}
  indent={indent}
  output={output}
  setOutput={setOutput}
/>


Enter fullscreen mode Exit fullscreen mode

The FastAPI backend only exists for two things: storing anonymous analytics so the homepage can show genuinely popular tools, and handling shareable links so you can generate a short URL and send your formatted output to a teammate. That's it. The backend never sees your tool input.

How all 30 tool pages are built from one route

This was the part I was most deliberate about. I didn't want 30 separate page files. Instead, every tool page is driven by a single dynamic route at /tools/[slug] and a central tool registry.

The registry is two files. toolRegistryData.tsx is server-safe — it holds all the metadata for each tool: the slug, title, description, category, and SEO fields. toolRegistry.ts holds the actual component references and is client-side only.


// config/toolRegistryData.tsx (simplified)
export const toolRegistryData: Record<string, ToolMeta> = {
  'json-formatter': {
    slug: 'json-formatter',
    name: 'JSON Formatter',
    description: 'Beautify, minify, validate, and tree-view JSON',
    category: 'Formatters',
    componentKey: 'JsonFormatter',
    // ... actions, seo, relatedTools
  },
  'jwt-decoder': {
    slug: 'jwt-decoder',
    name: 'JWT Decoder',
    description: 'Decode and inspect JSON Web Tokens',
    category: 'Encoders / Decoders',
    componentKey: 'JwtDecoder',
    // ... actions, seo, relatedTools
  },
  // ... 28 more
};


Enter fullscreen mode Exit fullscreen mode

At build time, Next.js reads the registry and statically generates all 30 tool pages. The [slug]/page.tsx file looks up the slug, pulls the matching component from the registry, and renders it inside ToolPageLayout. One route, 30 pages, all generated at build time.


export async function generateStaticParams() {
  return getAllToolSlugs().map((slug) => ({ slug }));
}


export default async function ToolPage({ params }: PageProps) {
  const { slug } = await params;
  const tool = getToolMeta(slug);
  if (!tool) notFound();
  return <ToolPageLayout tool={tool} />;
}


Enter fullscreen mode Exit fullscreen mode

The full stack

Frontend

  • Next.js 16 with SSG and SSR
  • React 19
  • TypeScript
  • Tailwind CSS 4
  • Monaco Editor — the same editor that powers VS Code, used for all code input and output fields

Backend

  • FastAPI (Python) — lightweight, fast to write, easy to deploy in Docker
  • MongoDB — stores analytics events and shared link data
  • Redis — caching layer for the popular tools API
  • AWS S3 — file storage

Infrastructure

  • Vercel for the frontend — automatic deploys on every push to main, global CDN, zero config
  • Railway for the backend — Dockerised FastAPI, simple to manage

Every tool page has JSON-LD structured data and full meta tags generated from the registry, which gives Google enough to understand what each page is about without any extra work.

What I'd do differently

The split between toolRegistryData.tsx and toolRegistry.ts exists because of a Next.js SSR constraint — you can't import React components on the server side when using certain rendering modes, so I had to separate the metadata from the component references. It works, but it means every new tool requires an entry in two files instead of one.

If I were starting over I'd design the registry as a single source of truth from the beginning and handle the server/client boundary differently — probably using dynamic imports with React.lazy and a single registry file that the server uses for metadata and the client hydrates with the actual component. The current solution is fine, it's just more maintenance surface than it needs to be.

Try it and tell me what's missing

The site is live at dev-toolbox.io. Every tool runs in your browser, nothing is stored, and there's no account.

Which tool would you add next? Drop it in the comments — I'm actively adding tools based on what people actually need.

Top comments (0)