Update (OCTOBER 05, 2016 ): BOOM! Unfortunatelly RethinkDB is shutting down! https://rethinkdb.com/blog/rethinkdb-shutdown/ Sad news :/

Imagine if you didn't need to write your backend because you got it for free. If all you needed to do was write your front-end app and connect it to a ready-to-use and very flexible backend. If you know platforms like Meteor or Firebase you can probably imagine it with ease. But as we all know, every tool has its own restrictions. Firebase is not open source (as far as I know) and in the long run it could be not enough. Meteor is too monolithic and not very flexible. I’m not only saying what I’ve heard. I’ve been active in the Meteor community since Meteor version 0.6.

So why not discover new horizons? Maybe it’s time?

In this article, I want to take a closer look at Horizon - a realtime, open-source backend for JavaScript apps. Built by the RethinkDB team.

I want this article to be just an introduction to the Horizon and RethinkDB, but we'll be learning it by looking at simple TODO app built with Horizon, React and Webpack. It will be a ready-to-use boilerplate too. You'll find a lot of cool stuff from my react-boilerplate here because I've used it as a base for the client side app. So, I hope that it will be more than just some boring info about Horizon and RethinkDB.

What we'll cover here:

RethinkDB – why there is so much hype about it now? Horizon – quick introduction react-hz – like Redux, but in the Horizon world React/Webpack/Horizon TODO app example

RethinkDB – why there is so much hype about it now?

Before we look into the codebase, I need to provide some basic info about RethinkDB and Horizon. Just to be clear, I don't know RethinkDB very well (yet!), but I can already see why it is gaining popularity so fast. First of all, it’s specially designed to be a database for real-time apps. What does that mean? It has mechanisms which allows the database to push the changes to your app. You don't need to do inefficient polling or use other solutions like Oplog in MongoDB. For sure it’s very important when you want to build a bigger real-time app. I don't want to go deep into this here so if you want to learn why this is so good, I encourage you to read a blog post: Advancing the realtime web.

The second cool thing is its query language, which is really readable and clean. RethinkDB is a very good mix of the NoSQL and SQL-like database. RethinkDB doesn't support SQL, but its query language can do nearly anything SQL can do, which in my opinion is a very strong point.

If you already know SQL, there is a fantastic cheat sheet which compares SQL and RethinkDB's ReQL language: SQL to ReQL cheat sheet.

Another RethinkDB advantage is its Data Explorer. It is a very nicely presented app which is hosted for you when you run your Horizon app. You can read many interesting statistics there and you can also manage your data. Check out the introduction video:

Ok, enough about RethinkDB. It probably needs a separate article, and this one isn't about it for sure. Here we’ll only be using it through Horizon's API and we’ll be storing our todo items in it. I hope I'll be able to write more about it soon. For now let's see what Horizon is.

Horizon – quick introduction

Horizon is a real-time JavaScript backend which uses RethinkDB as its data layer. At the time of writing this, Horizon is in a very early stage although it is stable and I guess used in many apps already. It will probably change a little bit in the future, but the main assumptions should stay the same.

It was released in May 2016. You can read the release blog post: Introducing Horizon: build realtime apps without writing backend code.

So, what is it? You can think of it as an invisible backend which is configured and ready-to-use at the beginning of your project, so you don't need to do any additional work. Of course you can if you really want to. You can just grab some of its parts and integrate it with your own server and backend.

All you need here to start with Horizon is Node 4.4 or higher and some additional steps, let's see what it is. You need to:

Install RethinkDB: http://rethinkdb.com/docs/install/ Install Horizon from Npm: npm install -g horizon Initialize your custom app: hz init example_app Go to your app's folder: cd example_app Start the server: hz serve –dev

After you initialize your app, you'll have a very simple folder structure. You'll get two folders src and dist and that’s basically it. Your Horizon server will look for client files in the dist folder, but it won’t touch anything in there. So it is prepared to make usage of src folder for your development files and dist folder for your production. This is what we’ll do here in our demo app. It is a common usage of most development's workflows. I personally like this simplicity and separation.

In this article, we'll use a standard Horizon dev server and its configuration. You can of course configure the server as you want. Go and check the Embedding Horizon section to read more about it. For our purposes, let's stick to the standard dev server. In this case, we don't need to do anything more with it. It just works. It will also create and run RethinkDB instance for us.

You’re probably thinking how my client files in the dist folder connect to the server and RethinkDB. This is done through a special client side library provided by Horizon. You’ll find it as a standard client JavaScript file which you can include in the index.html file. Of course you can also use the Npm package and this is what we’ll do in our TODO app.

Now, let's take a look at the Horizon's Collection API which allows us to create collections and manage the data in the RethinkDB instance. I don't want to talk about the security stuff and permissions in this article. I'll try to write another one about it later, of course in the context of our example app.

Horizon's Collection API

Horizon's documentation is quite good. It could be better in my opinion, but for now at this stage it is good. You can read about Collection API and also I encourage you to take the Getting started with Horizon tutorial.

First of all, we need to know how to create our collection. You can do this on the client side.

We do this by:

const hz = new Horizon(); const messages = hz("messages");

So we've created a 'messages' collection here. Next we want to know how to add and remove elements from the collection. You can do this by:

messages.store({ id: 1, from: 'Bob', text: "Hello from RethinkDB" }); messages.remove(1); // or messages.remove({id: 1});

The last important thing is how we will display our data. You can do this by using the Collection.fetch() method which will return RxJS observable, so you’ll be able to subscribe to the data flow. Again, I don't want to go deep into the RxJS. For now it isn't that important in the context of our Horizon's API. You just need to know that if you want to use Horizon, you probably need to study RxJS a little bit too, which is worth it anyway.

Ok let's get back to our API:

If you want to display your data you can do something like:

messages.findAll({from: 'Bob'}).fetch().subscribe(msg => console.log(msg));

You'll get all messages from Bob in a collection at once. Then if there is new message from Bob you will get another console log with a collection of messages from Bob. Using RxJS here is a very nice feature because it could be used in apps based on React or Vue where you want to replace whole data sets. So, for example, in a very simple React app you could do something like:

(...) messages.findAll({from: 'Bob'}).fetch().subscribe(msg => this.setState({msg})); (...)

and then consume it like:

(...) this.state.msg.map(message => <div>{message.text}</div>); (...)

You'll find many other methods from the Collection API in the documentation’s Methods section. I don't want to write about them all here.

In our TODO app, we’ll use the tool which is designed for React and it will dramatically improve our workflow with Horizon and data layer. So let's see what it is.

react-hz – like Redux, but in the Horizon world

So why did I write that react-hz is like Redux? Because it is very similar when used with React. The author says it in his blog post too. I encourage you to read it. Of course you can still use Redux in this stack if you want. For example, if you want to manage your local state with it. I think it should work that way, although I haven't tested it yet, but I'm sure I'll do it at some point. For backend stuff and data sync, you can use react-hz, which has very similar API.

How does it work? It wraps our React components and passes Horizon's subscriptions and mutations methods to our components props. So as you can see this is very similar as in the React and Redux workflow.

All is reactive here. It is based on well-known data containers in the React world. You'll probably always want to separate your data containers components from your UI components which will only consume the data. With this tool, it is very simple and straightforward.

I really like the fact that when you know how to use Redux in the React app, you'll be able to switch very quickly.

You'll find examples in the author's blog post: Introducing React Horizon. Also check out the react-hz readme file.

I only hope that this library will be maintained. If not, there will probably be some other similar options to choose from soon. (One example: horizon-react it allows you to use Redux and Horizon together).

Ok, let's jump into the example.

React/Webpack/Horizon TODO app example

You can treat this example app as a complete Horizon/React/Webpack boilerplate. I plan to use it when building future apps with Horizon and React.

You can see the code of the app here. There is a release 1.0.0 for Horizon 1.1.3 and also 2.0.0 for Horizon 2.0.0. What I've done here is a standard Horizon project initialization and then I copied my client side React boilerplate into it. So now we have all development files in the src folder. We also have some other Webpack configuration files outside it and even client side tests with Mocha and Enzyme. We'll take a closer look at this soon. For now, let’s clone the repository:

$ git clone https://github.com/juliancwirko/horizon-react-webpack-boilerplate.git

How does the workflow look? You need to start two servers, one of which is a Horizon standard server. You can run it by: hz serve —dev . The second one is Webpack dev server which you can run in another terminal tab, of course from the same folder. You can run it by npm start . Before this, you need to install Npm dependencies if this is your first start. You can do this by npm install .

The Webpack server only serves client side files, but in this case it’s enough because it will connect with the Horizon backend separately. So we can develop our app and when we are ready we can build it ( npm run build ) to the dist folder. Then we will only need to run the Horizon server, which will serve static files from the dist folder.

So once again. When you develop your app, you should use two servers. The Horizon one and the client side Webpack server. But when you built your client side app, you can run only the Horizon server because it will grab your static files from the dist folder. For more details, read the README.md file in the repo.

Ok, lets get to the code.

In the root directory, you have some configuration files. So there are Webpack config files. Three files, one for the development environment, one for the test environment and one for the production build. As you can see, we have here also ESLint configuration (Airbnb styleguide) and Babel configuration so we can use all ES2015 goodies in the project.

We have some folders like __test__ , mocha-runner , .hz . The first two are just testing specs and configuration and the third one is a configuration folder from Horizon. You can learn about it in the Horizon docs. And of course we have the src and dist folders here. The most important is the src folder because we’ll build our front-end app in it. So, as mentioned before, after you clone the repo, you can run Horizon by hz serve --dev and also in the other terminal tab you can run the Webpack dev server by npm start . We can use Webpack's server which will serve development files from the src folder. When you run npm run build , Webpack will bundle all necessary files in the dist folder so from then on you can just use Horizon's server.

Let's see how it’s configured in the 'src' folder.

You can open the src folder in the repo. The first most important file is App.js. Here we integrate our React app with the Horizon backend. We use react-hz here. So we have something like:

import { Horizon, HorizonProvider } from 'react-hz'; const horizonInstance = Horizon({ host: '127.0.0.1:8181' }); ReactDOM.render( <HorizonProvider instance={horizonInstance}> <Router routes={routes} history={browserHistory} /> </HorizonProvider> , document.getElementById('app'));

As you can see, we've initialized Horizon's instance here and we use HorizonProvider which will pass all Horizon's subscriptions and mutations down to all subcomponents.

We can then consume that in our components. So, for example, let's take a look at Todo.js component.

As you can see, we use connect() method from react-hz package (Identical as Redux connect method. Isn't it?). Thanks to react-hz we can do something like:

(...) export default connect(Todo, { mutations: { removeTodo: (hz) => (id) => hz('todos').remove(id), editTodo: (hz) => (id, todo, finished, timestamp) => hz('todos').replace({ id, todo, finished, timestamp, }), }, });

Basically we've just passed mutations methods to the props of our Todo component. So, for example, we can use editTodo method in our edit event.

(...) const handleEdit = () => { editTodo(id, todo, !finished, timestamp); }; (...)

And in the component's jsx code:

(...) <button type="button" onClick={handleRemove}> <i className="fa fa-times"></i> </button> (...)

You pass the subscriptions the same way when for example you want to display the list of todo items. Let's take a look at the Home.js component when you can see the example.

Here we have something like:

export default connect(Home, { subscriptions: { todos: (hz) => hz('todos').order('timestamp', 'descending').limit(10000), }, mutations: { addTodo: (hz) => (todo, finished, timestamp) => hz('todos').store({ todo, finished, timestamp, }), }, });

And in the jsx of the component, we’ll map through the todo collection.

(...) <div> {todos.map((t, i) => <Todo id={t.id} todo={t.todo} finished={t.finished} timestamp={t.timestamp} key={i} />)} </div> (…)

This is basically all that we have in the demo app in the context of Horizon. You could of course use much more. It depends on what you want to build with Horizon. As I said before, this is just an introduction and basic boilerplate which you can find in the repository: horizon-react-webpack-boilerplate.

Let's sum it up

Horizon is a ready to use backend service without any additional configuration needed. Of course you can configure it as you need. You can also embed it in you current backend stack. Horizon uses RethinkDB as its database which I think (and hope) will be gaining popularity over time. It is a really good alternative for monolithic frameworks like Meteor.

We use here a react boilerplate which is integrated with Horizon through the react-hz library, but of course you can use something else if you want. This is just an example boilerplate.

I plan to write more about it when the new Horizon 2.0.0 version is battle tested. There are many interesting topics like RethinkDB possibilities, data aggregations, Horizon's auth, oAuth etc., security, and whole section about permissions looks very promising.

I'm looking forward to writing a real app using Horizon. I hope I find some time soon.

If you have suggestions or just want to comment on something, go ahead. You can do it here in the comments or you can find me on Twitter @juliancwirko.