The session transport was not that hard to get working. I had planned to use a different Node WebSocket library than I did, but it worked out pretty well. The browser version was nearly identical since their APIs were so close.
The real trick came when figuring out how to compile and package this up for both Node and the browser. TypeScript added an extra layer of configuration. I used to write libraries that would work for both browser and Node by exposing the API differently depending on whether a browser was detected. This project is slightly more complex because it has internal requirements and TypeScript has its own import/export stuff.
I thought it was interesting Browserify only wanted to export the last of multiple input files, so I re-exported the core types in the browser-specific entry script. And since we use Node's Buffer class quite a bit, I ended up also packaging in a tiny Buffer implementation made for the browser. I re-export this as well since we expect users to use it.
I think next on "q" project series, we'll try to get qrpc working in the browser. Then we'll be cooking. I'm also exploring how to get qmux and qrpc to work in a JXA environment.