Introducing Fauna Shell
Back in April, our team got together with the goal of assessing the current status of Fauna to try to see which areas we wanted to improve next. This group was a mix of people who had been at Fauna since the beginning, and people like me who had just joined the company.
As a new user, I struggled with how to get started using Fauna, so I raised the issue to the team. During our brainstorming sessions, we concluded that we needed to improve a couple of areas to provide the user with a blissful experience. One of them was overall documentation: information was usually there, somewhere, but it was hard to find for a new user. Since then, our team has been working hard on improving Fauna’s documentation. At the same time, we wanted to give the user a straightforward path to running their first Fauna query. The team knew we had great technology built into the database, but we needed to help users start experimenting with it as fast as possible.
An interactive shell was the answer to that, a tool where users could issue their Fauna queries while getting results from the database right away. And so the project Fauna Shell was born.
After you install the Fauna Shell, you can login from there to your Fauna Cloud account directly from the command line:
First, install the shell. If you're on a PC, you can install it with npm:
$ npm install -g fauna-shell
Alternatively, if you're on a Mac, you can install it with homebrew:
$ brew install fauna-shell
Second, log in with your Fauna credentials:
$ fauna cloud-login
Email: email@example.com
Password: **********
After those two steps, you are ready to start using your Fauna instance, for example by creating a database:
$ fauna create-database my_app
And then start playing with it from the interactive shell:
$ fauna shell my_app
Starting shell for database my_app
Connected to https://db.fauna.com
Type Ctrl+D or .exit to exit the shell
my_app>
Once in the shell, you will be able to start typing queries and receiving feedback right away:
my_app> CreateClass({ name: "posts" })
{ ref: Class("posts"),
ts: 1533753878043481,
history_days: 30,
name: "posts" }
User-centered design
This might seem like a small thing, but it's great when a user wants to get their feet wet with Fauna as fast as possible. The shell brings up an environment where instant feedback can guide the user while learning how to use Fauna.
Another important advantage of the Fauna Shell is that users don't need to setup a whole development environment to start using Fauna. In the past, there was the need to pick a programming language that had a Fauna client. Then, the user would have to install that client and learn the proper import directives that would let them use that client. From then on, they would have to write a query, compile or execute the program, see the results, and try again. With the Fauna Shell, we removed all those steps: The user writes queries and sees their results immediately.
Removing Obstacles
Something I enjoyed from the process of developing the Fauna Shell was how it was driven with a focus on providing the user with a pleasant experience. We wanted to remove obstacles. As mentioned above, one of them was the need for setting up a development environment just to use Fauna.
After discussions with Matt our CTO, and Summer our UX Lead, we came to the conclusion that Javascript would be the language that would host the shell. On one side, it provided an interactive environment, and on the other side, due to the web's popularity, almost every developer has worked with Javascript at least once during their professional lives.
Using our Javascript in plain node.js, we would write queries like this: query(q.CreateClass({ name: "posts" })). Basically a CreateClass directive would be passed to the query method, and that method would execute the query for the user. During the prototyping stages of the Fauna Shell, we used to write queries that way, but the more we typed those queries, the more we saw something was out. Every time we wanted to execute a query, we had to wrap it inside a query() function call. That sounded less than ideal. We decided to bring into scope the whole query module, removing that requirement.
By removing the need to wrap queries all the time and the need to scope function calls to the q. module, we left the user with a more ergonomic experience where they could focus on typing FQL expressions directly. The code shown above just became CreateClass({ name: "posts" }), letting the user focus on what’s important to them, for example, creating a class called posts.
Small Details Matter
Another thing we noticed as we worked with the shell was that the output we were receiving after sending queries to the database was far from ideal. For example, if you submitted the query CreateClass({ name: "posts" }), you would receive something like this:
{ ref: Ref(id=posts, class=Ref(id=classes)),
ts: 1527349751848648,
history_days: 30,
name: 'posts' }
As we kept seeing those results, and we tried to use them in future queries, we noticed that they couldn't be copy-pasted right back into the shell to be used in future queries. Our colleague Marrony worked on improving our faunadb-js driver so results would be pretty printed in a way that would allow for easy copy-paste:
{ ref: Class("posts"),
ts: 1532624109799742,
history_days: 30,
name: 'posts' }
While these examples all seem like small details, they help users have a nicer and more natural experience while using the Fauna Shell to learn how Fauna works. It's all about removing obstacles.
Finally, once we were ready to launch, we noticed that the shell provided no information to the user about to which server they were connected to, nor about which database they were using.
$ fauna shell my_app
Starting shell for database my_app
Connected to https://db.fauna.com:443
Ctrl+D or .exit to exit the shell
my_app>
Again, just a small detail that greatly improves the usability of the shell, providing users with the right context about where their queries are being sent. Nobody wants to suddenly delete all their information in the production database!
Conclusion
In this article, we not only wanted to give you a quick intro to the Fauna Shell, but also to provide you with some insight into how we develop products here at Fauna. We try to put ourselves in the shoes of our users and from that point try to see where our tools need to improve.
Also, even though in this case I was the lead for the Fauna Shell project, the whole work was a team effort: Our sales engineers helped us identify where the Fauna Shell was falling short. This feedback was looped between our UX lead, our CTO, and me so we could retrofit it into the project. Also, other colleagues stepped in and helped by improving other aspects of the product, like our JS driver, so at the end we could deliver a polished experience for our users while organically improving other areas of the system.
Of course, this is just the start of the road for the Fauna Shell project. We’re improving it further every day, and can't wait to hear from you about features you would like to see next.
If you enjoyed our blog, and want to work on systems and challenges related to globally distributed systems, and serverless databases, Fauna is hiring
Subscribe to Fauna's newsletter
Get latest blog posts, development tips & tricks, and latest learning material delivered right to your inbox.