Introducing txiki.js a tiny JavaScript runtime

txiki.js is a small and powerful JavaScript runtime. It’s built on the shoulders of giants: it uses QuickJS as its JavaScript engine, libuv as the platform layer, wasm3 as the WebAssembly engine and curl as the HTTP client.

I started working on txiki.js back in 2019, right when QuickJS was launched. I got hooked very quickly and wanted to try to build a tiny JavaScript runtime again. Again? Yeah, way back in 2016 I attempted the same thing, but using Duktape as my engine, that was SkookumJS. That attempt didn’t quite work out, mostly due to my inexperience, and constraints I set for myself (see the announcement post) so I ended up shelving the project.

Wisdom of hindsight

Despite SkookumJS being a failure, I learned a lot. I learned CMake, the Duktape API (very close to the Lua API apparently) but most importantly I discovered how not to build that runtime I was dreaming about.

My main takeaways:

  • If the runtime is not going to be Node compatible it must be browser compatible (API wise)
  • Relying on external tools (like Node) to prepare the core JS bundle simplify things a lot, since you can transpile the code to whatever your JS engine supports
  • With ES6 and promises a runtime that does not incorporate the concept of an event loop seems unattainable
  • C and CMake are still solid choices, we can wrap anything!

txiki.js is born

It’s fair to say txiki.js would not have materialized without QuickJS. It supports ES2020, ES modules, comes with a sample standard library, the C API is incredibly easy to use, and it’s extremely easy to embed in other projects, it’s just a handful of C files. It had it all.

So I got to work. I chose libuv for the event loop and ported the little standard library QuickJS came with to it. This gave me the confidence I was on the right path.

By this time Deno had already made an appearance in the scene. Some of its propositions sounded really appealing to me, specially the fact that it targets browser APIs and there is no require, just ESM modules. The people behind Deno definitely know what they are doing, and that further cemented some of the ideas I wasn’t sure about.

I kept developing txiki.js slowly but surely. Some of the important milestones were the integration of wasm3 to provide WebAssembly and WASI capabilities, and curl for XHR / fetch.

It’s now pretty functional, and I realized I forgot to actually post about it here, so I guess it’s time to “announce” it.


A couple of weeks ago FOSDEM took place, virtually. It’s one of my favorite conferences and when the call for papers opened I thought to myself “let’s use this as an opportunity to get txiki.js in better shape and tell the world”. Thankfully my talk proposal was accepted and I talked about my journey from SkookumJS to txiki.js. You can check it here.

txiki.js at FOSDEM 2022


I plan on continuing the journey I outlined in the talk with this new found enthusiasm. You can follow along on GitHub.

Leave a Reply

Your email address will not be published. Required fields are marked *