📟 Building Web based UIs for Terminals using JavaScript

For a developer, most of his/her time is spent on the code editor or the terminal. As web developers, we mostly target browsers and nowadays even native mobile platforms (thanks React Native). But I recently figured out you could also target terminals for your web-based UIs.

What do I mean by this ?

Type: curl wttr.in in your terminal. This console app from Igor Chubin written in python is what inspired me to write this blog.

wttr.in by Igor Chubin

Amazing! right. So, I decided to dig a bit deeper and find out how it is done.

ANSI Escape Codes

ANSI escape sequences are a standard for in-band signaling to control the cursor location, color, and other options on video text terminals. Certain sequences of bytes, most starting with Esc and ‘[‘, are embedded into the text, which the terminal looks for and interprets as commands, not as character codes.

In essence, ANSI Escape codes are characters that are interpreted by the terminal in a special way. These codes can be used to add colors to the text, control cursor location, etc. All major terminals support these codes including Windows 😉.

In 2016 with Windows 10 “Threshold 2”[1] Microsoft unexpectedly started supporting ANSI escape sequences

The exact details of how ANSI escape codes work will not be covered here. There is an excellent Wikipedia article on that here: https://en.wikipedia.org/wiki/ANSI_escape_code


More examples for inspiration before we code

Before we go ahead and hack this out, I wanted to share more awesome examples:

rate.sx by Igor Chubin

curl rate.sx

Another one from Igor Chubin . This one even has charts 😲. That’s just crazy!!

parrot.live by Hugo

curl parrot.live

This one is from Hugo. This has an animated party parrot !!

How cool is that !!!

byemck.atulr.com by Atul

curl byemck.atulr.com

This one I built for last day at my previous job. Wanted to say goodbye in style 😉

https://github.com/master-atul/byemck

There are more examples listed at: https://github.com/chubin/awesome-console-services


Why will anyone build these ?

  • So one interesting thing you will notice is that when you hit wttr.in using a browser, you get a simple HTML & CSS based web page. But when you hit it using curl or wget you will get an ANSI coded text as the response. So, now you can target terminal users (devs) directly. For example, devs can now view an online documentation that is color-coded and syntax highlighted directly on their terminals without opening a web page on a separate browser.
  • Curiosity 😬; Don’t know about you, but these demos were convincing enough for me to try building this using NodeJS.

Lets build these using JavaScript (NodeJS)

The complete source code can be found here: https://github.com/master-atul/console-web-ui

First step: Simple hello world

Since this is a web API, I would be using express.js to build a simple API server using nodejs. Follow the guide here: https://expressjs.com/en/starter/hello-world.html to make a simple express js API server.

Now type: node app.js to launch the server.
In another terminal type: curl localhost:3000. You should see :

There, hello world is ready 😆

Next step: Add colors to the text

As mentioned before, we need ANSI codes for the colored output to the screen. Fortunately, there is a really nice npm module for that. https://github.com/chalk/ansi-styles

Let’s see what hello world in color looks like.

app.js

You should get the following output on curl http://localhost:3000/hello

What about animations ?

Animations are a continuous sequence of frames that give an impression that something is moving. To achieve that we need to send multiple frames to the client side and clear out the old frame before showing the next.

  • To send multiple frames of data to the client side we will use node streams .
  • To clear out screen before displaying next frame we can use a special ANSI code \033[2J\033[H

Let’s say we want to show the current server time on the console that changes with every second. So our output would look like this:

animated current time display using curl — NOTICE THE SECONDS (it changes 😆)

The code looks like this:

animation example

What if same route can be used for both browser and terminal ?

Ideally, if we hit a URL on a browser we should get the HTML and CSS response, while if we hit it from curl or terminal we should get the response in the text format that terminal understands.

What do I mean ?
Okay try opening wttr.in on the browser — You should see HTML, CSS based website loading up. Now try curl wttr.in , the same URL now returns text-based output that the terminal can understand.

To do this in expressjs. We will use the concept of next .

Outputs:

Now when you run
curl http://localhost:3000/hello

⬅ You get this

If you open up the link in your browser, you ‘ll get the HTML page you made.

This example is hosted on heroku at https://console-web-ui.herokuapp.com/

All the code for this blog is at :
https://github.com/master-atul/console-web-ui/

I hope this was fun 😬🎉