Hello again my little Stardancers ✨ It’s devlog time, and this one comes with a confession: I moved a real app onto inkan.
Not a todo list. A real one with 55 routes, file uploads, backups of a couple hundred MB, sessions and a mail setup. It ran on Express, and I wanted to know what happens when inkan has to do real work. Turns out: mostly fine. But not completely. And that “not completely” turned into inkan 0.5.0
The first problem was request bodies. inkan read every body into memory, with one 1 MB limit for the whole app. Fine for JSON, less fine for “hey, can I upload this 2 GB backup?” No ❤️ So I paused the migration and fixed the framework first.
0.5.0 brings t.binary() for files sent as the request body, and t.stream() for real streaming uploads: your handler gets the upload chunk by chunk, so the file never sits in memory. Limits are per route, so one endpoint can take 2 GB while the rest stays at 1 MB. On the way I found a fun bug: when a stream hit its limit, or the server answered 401 before the upload was done, the connection could just… hang. Fixed, the response arrives and the rest gets drained properly
Then the frontend. Now there’s serveStatic(): hashed assets cached for a year, index.html never stuck in a cache, and unknown routes fall back to the SPA. Except /api, where a typo gets a real 404 instead of your entire frontend 💅 compress() does Brotli and gzip, streams included. In the app I migrated, the bundle went from 75 KB to 18 KB.
There’s also ctx.ip for the login rate limiter (Bun and Deno too), per-route body limits and app.bodyFor() for adapter authors. And the benchmarks say no potato: every scenario stayed within ±4% of main on the same GitHub runner.
And then something else happened: inkan got integrations 🧩 All in one repo at github.com/inkanjs/integrations.
@inkanjs/vite runs your API inside the Vite dev server, so frontend and API share one port. No proxy, no second terminal, just npm run dev. The API reloads on every save, each reload counts as a fresh restart so your timers don’t multiply, the docs and inspector links show up in Vite’s banner, and a broken API shows up in Vite’s error overlay.
@inkanjs/next turns an inkan app into Next.js route handlers with one line, works with the Pages Router too, and has direct(app): a typed client for Server Components that calls your API in the same process. CI builds and starts a real Next.js app, because “works on my machine” isn’t a testing strategy.
@inkanjs/query is for TanStack Query: keys and types straight from the API paths, failed responses as errors with the problem document, and a retry() that won’t retry a 404 until the heat death of the universe.
@inkanjs/uws runs inkan on uWebSockets.js, with graceful shutdown and HTTPS, and it’s the fastest way to run inkan. Nuxt, SvelteKit, Astro and Remix don’t even need a package: app.fetch is enough, and the repo has recipes.
And the migration? All 55 routes run on inkan now, split into files by area instead of one 1300-line index.js. Every test passes, the frontend didn’t change a single line, and dev went from two processes, two ports and a proxy to npm run dev on one port. Express, compression and concurrently are gone, 74 packages fewer
A real project is great at showing you where your framework doesn’t hold up. inkan had a few of those places. Now it has fewer.
npm install @vxnsin/inkan@0.5.0
See you next time, Stardancers 🌙