I highly recommend Bubbletea. I used it for an internal tool, and it combined with Viper makes an easy-to-use TUI application development easy.
Though it uses an approach more similar to Elm than to React.
I recently used Ink to build a small debugging CLI for a websocket-heavy project of mine. All it does is subscribe to a specific channel and print out the message or send dummy data when I press a specific button. The frontend websocket code could be reused easily so it was very fast to do.
Very convenient to run multiple terminals as multiple clients in parallel. Much nicer at least than something like Postman for Websocket tests.
Full screen took some time to get right and still flickers when using iterm 2. But it does work on the apple terminal and for now I am happy with that.
My only issue is that Ink does not support nested rendering / overlays, i.e. modals.
What role did Ink serve? I mean couldn’t you have just logged to console?
I’m trying to figure out if Ink enabled you to do something at all, made it easier, or you just liked using it. All of which are fair. It seems like you just liked using it.
I think it’s rerendering the “UI” on data updates. Basically exactly the readme for ink. It’s a single log line of output, but it’s repainted in place, not appended to stdout.
Sure you can do that other ways. Personally I’d love to build terminal tuis with react component!
what the other comment said, it replaces output and looks like a proper terminal UI. But it also adds features for hotkeys, progress bars, text input etc.
I have it integrated into a bigger CLI project where only a few commands enter the UI. Most of them just render to stdout and are meant to be pipeable
I'd be cool to use your approach to build a "frontend" for monitoring Python's TQDM output. Especially useful for multiprocess applications with scores of independent, long running processes like data ingestion pipelines. TQDM does support monitoring multiple processes but is not flexible enough for all use cases.
> I recently used Ink to build a small debugging CLI for a websocket-heavy project of mine.
why not just write tests?
i'm getting super down voted on this, but come on... why? this person built some buggy utility and those bugs can end up causing more problems than just writing tests in the first place.
no wonder we end up with such buggy junk software... people... write tests!
Building a simple debugging tool to monitor your program for possible inconsistently reproducible bugs and having unit tests are not mutually exclusive concept. You're getting downvoted because you're making condescending assumptions about the developer.
I would argue that, based on my experience, most of the code I'm debugging is not my code so it really doesn't matter how many tests I write because the problem is I misunderstood how a library or someone else's code I'm using works or there's a bug I can't find just with tests.
I tried (and sort of failed) to build something like this for rust [0] (warning it's broken at the moment).
It's a lot harder than I expected. Especially since the terminal has no notion of focus, and with Rust it's really hard to not just clone everything you get your hands on when writing a UI library. The borrow checker really feels like it gets in the way of features like signals [1], and partial re-renders.
Very neat idea. I love how decoupled React is from the different renderers, and how well its paradigm of "render a tree of things that updates as state changes" translates to different kinds of UIs
React is indeed really neat. At the same time, however, I miss the visual drag & drop GUI designers that were in vogue a few decades ago. HTML and CSS are the tragedy of modern UI design.
The drag and drop GUI designers used to work because most people were using screens that were approximately the same size and resolution for the most part back then. That is no longer the case today when there is pressure to support everything from a smart watch all the way up to a UHD 4K monitor or TV. Fixed layouts are also much more difficult to localize and translate to other languages than modern layout systems.
It's one of those "grass is greener on the other side" situations.
I'm currently bouncing back and forth between VB6 and HTML/CSS and yeah sometimes it is nice to just quickly drag something into place, but other times I really wish I could just use a layout system like CSS Grid (or Flexbox) and give it all the items I need and let it figure out how to lay it out.
For instance, recently I had to edit some "tables" in VB6 that turned out to have been hand-drawn with pixel-perfect lines and changes were incredibly slow and I would have murdered for that to be in HTML/CSS.
Sometimes I like (and miss) the best of both worlds in XAML where it has drag-and-drop design tools, but also the copy-and-paste and handwrite support of XML, and it has modern layout tools like Grids for auto-layouts/responsive layouts.
I view the rise of React and especially Electron as the failure of things like GTK, Qt, and e.g. Swing to make a useable cross-platform GUI toolkit that isn't a total nightmare to work with / compile / debug / install / package...it's literally easier to ship [most of] an entire web browser instead. That's insane to me.
you can use drag and drop GUI builders on top of react. there's been a lot of attempts at that. a significant recent effort from Wix: https://www.codux.com/
I worked with many different UI kits. From native windows to Ubuntu to automotive to embedded to Android to Apple. I find HTML and css by far the most convenient UI toolkit there is. Never have creating UIs been so easy as with css. A relief it is.
One of my favorite side projects (from several years ago now) was a custom renderer implementation that let one use React to manage the parts of an Electron app outside the page being rendered. [1] I never found the time to actually go through and make it robust enough to use in a production setting, but I remember being very pleased with how much easier it was to use than the native Electron APIs.
This looks amazing. Can anyone talk about the added overhead of this? I'm assuming having to bundle all of Node.js/V8 in your executable is one of them. Plus extra processing to re-render the tree for changes.
I'm wondering if this is worth it to use for very simple CLI scenarios that can be addressed by more lightweight libraries like Cobra. Maybe so your client-side business logic can stay more unified?
It's also really funny to me that what is considered the absolute simplest use case in programming – write a program that outputs a line of text to the console – is still not free from the Node/npm/React experience.
> I'm wondering if this is worth it to use for very simple CLI scenarios that can be addressed by more lightweight libraries like Cobra. Maybe so your client-side business logic can stay more unified?
I'd say yes. Performance will be "good enough". Disk space use or whatever other nonsense HN people love to fret about will be "good enough". And the gains from reusing the same stack everywhere are worth it. I used to think writing little helper scripts in a JVM language (Scala) was an unacceptable overhead, then I realised how low the practical cost was.
> I'm assuming having to bundle all of Node.js/V8 in your executable is one of them
I guess you could expect Linux distros to come with Node (though it's probably a quite dated release). Looking at standalone binaries, both bun.sh and Node.js are about 30MB. In comparison, Python 3.10 is 9MB and starts slower than bun but faster than Node. Bundling is easy too, you can take a loot at vercel/pkg https://github.com/vercel/pkg
React kind of reminds me of English. It is ubiquitous for reasons that essentially boil down to imperialism. It imposes at least as many problems as it solves. There is ample evidence that we were getting along fine (if not better) without it. At some point it became the only language many young people know.
And if React is like English, then using it to write a CLI is like using Webster's dictionary to translate hieroglyphs.
That may be but at least for my own case, web development became an order of magnitude more pleasant when React came out. I keep an eye on new frameworks but so far, nothing has caught my attention enough for me to switch.
Yeah, React has always struck me as a bit of a Frankenstein approach to application development. I don't get the appeal, but then I already know how to develop complex applications. If someone can explain if it has any advantage over any native windowing frameworks I'd be interested in reading that.
> Can anyone talk about the added overhead of this? I'm assuming having to bundle all of Node.js/V8 in your executable is one of them.
The primary use case for this would be CLI apps that are already written in JS or TypeScript.
Trying to use this as a front-end for a CLI app written in a different language isn't impossible, but it's a lot of extra work. You'd be better off looking for a similar CLI library in the language you're already using.
Ink is amazing for quickly hacking together TUIs. I recently did so with Nbb (Node Babashka) and and enjoyed the experience overall.
My only real complaint is how everything in your VDOM seems to re-render on a state change. IIRC this is being addressed [1], but is something to be mindful of, especially if your users may be using slow machines.
[1] https://github.com/charmbracelet/bubbletea
[2] https://github.com/textualize/textual
[3] https://github.com/fdehau/tui-rs
https://www.google.com/search?q=Ruby+TUI
You can see this discussion post about it [2].
[1] https://github.com/tui-rs-revival/ratatui
[2] https://github.com/fdehau/tui-rs/issues/654
https://www.ruby-toolbox.com/categories/terminal_ui?display=...
Very convenient to run multiple terminals as multiple clients in parallel. Much nicer at least than something like Postman for Websocket tests.
Full screen took some time to get right and still flickers when using iterm 2. But it does work on the apple terminal and for now I am happy with that.
My only issue is that Ink does not support nested rendering / overlays, i.e. modals.
I’m trying to figure out if Ink enabled you to do something at all, made it easier, or you just liked using it. All of which are fair. It seems like you just liked using it.
Sure you can do that other ways. Personally I’d love to build terminal tuis with react component!
I have it integrated into a bigger CLI project where only a few commands enter the UI. Most of them just render to stdout and are meant to be pipeable
why not just write tests?
i'm getting super down voted on this, but come on... why? this person built some buggy utility and those bugs can end up causing more problems than just writing tests in the first place.
no wonder we end up with such buggy junk software... people... write tests!
Just not as good for websockets
Ink allowed me to quickly add a simple admin and debug UI
Ok.... why?
It's a lot harder than I expected. Especially since the terminal has no notion of focus, and with Rust it's really hard to not just clone everything you get your hands on when writing a UI library. The borrow checker really feels like it gets in the way of features like signals [1], and partial re-renders.
[0]: https://docs.rs/intuitive/latest/intuitive/ [1]: https://preactjs.com/guide/v10/signals/
I'm currently bouncing back and forth between VB6 and HTML/CSS and yeah sometimes it is nice to just quickly drag something into place, but other times I really wish I could just use a layout system like CSS Grid (or Flexbox) and give it all the items I need and let it figure out how to lay it out.
For instance, recently I had to edit some "tables" in VB6 that turned out to have been hand-drawn with pixel-perfect lines and changes were incredibly slow and I would have murdered for that to be in HTML/CSS.
Sometimes I like (and miss) the best of both worlds in XAML where it has drag-and-drop design tools, but also the copy-and-paste and handwrite support of XML, and it has modern layout tools like Grids for auto-layouts/responsive layouts.
Maybe I'll revisit this sometime. :)
1: https://github.com/mhink/react-ionize
I'm wondering if this is worth it to use for very simple CLI scenarios that can be addressed by more lightweight libraries like Cobra. Maybe so your client-side business logic can stay more unified?
It's also really funny to me that what is considered the absolute simplest use case in programming – write a program that outputs a line of text to the console – is still not free from the Node/npm/React experience.
I'd say yes. Performance will be "good enough". Disk space use or whatever other nonsense HN people love to fret about will be "good enough". And the gains from reusing the same stack everywhere are worth it. I used to think writing little helper scripts in a JVM language (Scala) was an unacceptable overhead, then I realised how low the practical cost was.
I guess you could expect Linux distros to come with Node (though it's probably a quite dated release). Looking at standalone binaries, both bun.sh and Node.js are about 30MB. In comparison, Python 3.10 is 9MB and starts slower than bun but faster than Node. Bundling is easy too, you can take a loot at vercel/pkg https://github.com/vercel/pkg
And if React is like English, then using it to write a CLI is like using Webster's dictionary to translate hieroglyphs.
The primary use case for this would be CLI apps that are already written in JS or TypeScript.
Trying to use this as a front-end for a CLI app written in a different language isn't impossible, but it's a lot of extra work. You'd be better off looking for a similar CLI library in the language you're already using.
Stating the obvious, but if you are outputting a line of text to the console, don't use this.
For example using React to generate a simple "hello, world" style website is overkill but not totally unthinkable. Is it worse for the CLI case?
[1]: https://www.inklestudios.com/ink/
My only real complaint is how everything in your VDOM seems to re-render on a state change. IIRC this is being addressed [1], but is something to be mindful of, especially if your users may be using slow machines.
[1] https://github.com/vadimdemedes/ink/issues/21