A single-page developer toolkit — 35 instruments that run entirely in your browser. No API routes, no database, no auth, no telemetry: every route prerenders to static HTML and all computation (hashing, parsing, encoding, QR, EXIF) happens client-side.
Built with Next.js 15 (App Router), React 19, TypeScript, Tailwind CSS v4, and shadcn/ui, dressed in a Swiss Industrial Print design system: paper substrate, carbon ink, one hazard-red accent, zero rounded corners.
Live at kit.ixtj.dev.
| Tool | Route |
|---|---|
| Base64 Encoder/Decoder | /converters-parsers/base64-encoder-decoder |
| Base64 Image Converter | /converters-parsers/base64-image-converter |
| chmod Calculator | /converters-parsers/chmod-calculator |
| Color Converter | /converters-parsers/color-converter |
| CRON Parser | /converters-parsers/cron-parser |
| curl to fetch | /converters-parsers/curl-converter |
| Data Converter | /converters-parsers/data-converter |
| JSON Parser | /converters-parsers/json-parser |
| JWT Decoder | /converters-parsers/jwt-decoder |
| Number Base Converter | /converters-parsers/number-base-converter |
| Regex Tester | /converters-parsers/regex-tester |
| Text Case Converter | /converters-parsers/text-case |
| Timestamp Converter | /converters-parsers/timestamp-converter |
| Timezone Converter | /converters-parsers/timezone-converter |
| Unit Converter | /converters-parsers/unit-converter |
| URL Encoder/Decoder | /converters-parsers/url-encoder-decoder |
| URL Parser | /converters-parsers/url-parser |
| Tool | Route |
|---|---|
| Barcode Generator | /generators/barcode-generator |
| Gradient Generator | /generators/gradient |
| Hash Generator | /generators/hash |
| HMAC Generator | /generators/hmac-generator |
| ID Generator | /generators/id-generator |
| Lorem Generator | /generators/lorem-generator |
| Password Generator | /generators/password |
| Port Number Generator | /generators/port |
| QR Code Generator & Reader | /generators/qr-code |
| SVG Placeholder Generator | /generators/svg-placeholder-generator |
| TOTP Generator | /generators/totp-generator |
| UUID Generator | /generators/uuid |
| Tool | Route |
|---|---|
| API Directory | /viewers-miscellaneous/api-directory |
| Diff Viewer | /viewers-miscellaneous/diff-viewer |
| HTTP Status Codes | /viewers-miscellaneous/http-status-codes |
| Image Metadata Viewer | /viewers-miscellaneous/image-metadata-viewer |
| Token Counter | /viewers-miscellaneous/token-counter |
| Unicode Inspector | /viewers-miscellaneous/unicode-inspector |
One archetype per substrate — the theme toggle (sidebar, next to the filter) switches wholesale between two fully-committed modes; substrates are never mixed within a mode. Both palettes are tuned for legibility (astigmatism-friendly): softened substrate extremes, borders below text luminance, no overlay textures, mono text at weight 500, and red never used as small text on dark.
Light — Swiss Industrial Print (default):
- Substrate — paper
#F2F1EB, panel#FCFCFA, muted paper#E9E8E2 - Ink —
#1C1B18for text, borders, and structural rules (1px internal, 2px outer panels) - Hazard red —
#E61919, the single accent. Vital data, errors, selection, focus. Never decoration. - Typography — Inter Black for macro headings (uppercase,
-0.04emtracking, compressed leading); IBM Plex Mono at weight 500 for everything data-adjacent. Korean glyphs fall through to Pretendard Variable in both stacks (per-glyph fallback). Labels and chrome are uppercase micro type; user data stays verbatim. - Geometry — square corners everywhere. No gradients, no backdrop blur, no soft shadows. Floating layers (dialogs, popovers, toasts) get a hard
4px 4px 0offset shadow instead.
Dark — Tactical Telemetry / CRT (class="dark", LIGHT / SYSTEM / DARK toggle):
- Substrate — deactivated CRT
#131312background,#181816panels,#22221Fmuted - Phosphor — warm
#D8D5CDas text and inverted-action fills (--inkflips to phosphor,--paperto CRT — every primitive inverts with the token); structural borders sit below text luminance (#8E8C85) so the grid doesn't vibrate against glyphs - Hazard red — fills stay
#E61919; red-as-text lightens to#FF6B5Ein dark (--hazard-text) - No texture overlays — noise grain and scanlines are omitted for readability
Tokens live in app/globals.css (--ink, --paper, --hazard-text and the shadcn token set); all 50+ primitives in components/ui/ implement the system, so new tools inherit it by using them.
Bun is recommended; npm/pnpm/yarn also work.
bun install
bun run devOpen http://localhost:3000. No environment variables are required — the app has no server dependencies to configure.
| Command | Action |
|---|---|
bun install |
Install dependencies |
bun run dev |
Dev server (Turbopack) |
bun run lint |
ESLint (next/core-web-vitals + next/typescript) |
bun run build |
Production build |
bun run start |
Serve the production build |
Change order: edit → lint → build → commit. No test runner is configured.
app/
layout.tsx # Shell: sidebar, mobile nav, fonts, I18nProvider, ThemeProvider, toasters
page.tsx # Homepage: spec-sheet index of all tools
globals.css # Design tokens + base layer
manifest.ts, icon.png, ... # PWA manifest + app icons
converters-parsers/<tool>/ # Client-side tool pages (17 tools)
generators/<tool>/ # 12 tools
viewers-miscellaneous/<tool>/ # 6 tools
components/
ToolPageLayout.tsx # Bordered panel wrapper for tool pages
ToolHeader.tsx # Macro-typography header bar
theme-provider.tsx # next-themes wrapper
MobileNavToggle.tsx # Sheet trigger for the mobile nav
ui/ # shadcn/ui primitives, restyled to the system
hooks/
use-mobile.ts # Viewport < 768px flag
use-persistent-state.ts # useState persisted to localStorage (`devkit:` prefix)
data/
api-list.json # Static dataset for the API Directory
lib/utils.ts # cn() helper
lib/i18n/ # en.ts (source of truth) + ko.ts (typed Dictionary) + provider/hook
public/ # Static files
All tool pages are client components ("use client"). There are no server components with data fetching, no API routes, and no server actions anywhere in the app.
English + Korean, no URL routing, no middleware — the app stays fully static.
- Dictionaries —
lib/i18n/en.tsis the source of truth (fully commented for translators);lib/i18n/ko.tsis typedDictionary = typeof en, so a missing Korean key is a compile error (bunx tsc --noEmitis the parity gate). No JSON message files, no i18n runtime deps. - Usage —
const { t, locale } = useI18n()thent("tools.<camelCaseFolder>.<key>", vars);{var}placeholders interpolate at runtime. - Detection — client-side post-mount: stored explicit choice (
localStorage["devkit:locale"], JSON-encoded) > browser languages > English. Only explicit toggles persist; auto-detected values are never written. - Switcher — second row inside the sidebar theme box (
EN | 한국어), theme buttons ordered System / Light / Dark. - Untranslated by design — metadata/OG tags, technical tokens (
JSON,SHA-256,chmod…), tool outputs, and decorative literals.
Three files:
-
app/<category>/<tool-name>/page.tsx— the tool page:"use client"; import { ToolPageLayout } from "@/components/ToolPageLayout"; import { ToolHeader } from "@/components/ToolHeader"; import { SomeIcon } from "lucide-react"; export default function ToolPage() { return ( <ToolPageLayout header={<ToolHeader icon={<SomeIcon aria-hidden />} title="Tool Name" />} > {/* tool UI */} </ToolPageLayout> ); }
-
components/ui/sidebar.tsx— add the entry to its category in thegroupsarray (labels are uppercase there:"GENERATORS"). -
app/page.tsx— add it to the matching category in thecategoriesarray (titles are title-case there:"Generators").
Follow the design contract above: use the existing primitives, label compartments in mono uppercase, keep user data verbatim, and reserve red for things that matter. The homepage unit count is computed from categories, so there is no counter to update.
The production build is fully static — every route is prerendered. Deploy to Vercel, or any host that can run a Next.js build (next start). Nothing to configure.
Inspired by utilsfor.dev by Jairon Landa.
© 2026 IXTJ