W3CSVG

Announcing heliosRX

A universal ORM library for Firebase Realtime Database and Vue

The future of the web is real-time. With Firebase Realtime Database Google offers a great product to write real-time web applications without the hassle of setting up an infrastructure yourself. Simply create a project and within minutes you will have your backend up and running and can start developing.

While getting started with Firebase is easy, you’ll soon run into some problems as your application is becoming increasingly more complex:

  • Nested data: With Realtime Database all your data is basically stored as one big JSON tree, which means you can nest your data as deep as you want, which means you have to somehow manage where your data is located
  • No Schema: While NoSQL is great as it gives you a lot of flexibility required in the early stage of development, you need more and more structure while you go
  • Security rules: If you don’t want that ANY user can write ANYTHING into your database (which you probably don’t want), you have to write security rules
  • Code sharing: Modern apps are usually not just web applications. Soon you will want a mobile app or will need to write backend code for more advanced server-side logic
  • Vendor Lock-in: Let’s face it; once you decide to go with Realtime Database you get locked in. The only way out is to rewrite major parts of your application, which has huge transaction cost.
  • Dealing with reactivity: In many cases, changes that were made in the database should be reflected in the client’s UI

The story of heliosRX

About 1.5 years ago, we started working on a new task- and time-management app that makes it easy to plan out your day, week or month, while still having the usual task management tools like a Kanban board.

As a bootstrapped startup we were forced to spend our time and resources wisely, which is why we decided to go with Firebase as our backend. heliosRX is the result of working with Firebase and building a large application on top of Vue and Firebase. It is the foundation on which our web application was built.

The goal of this project is to:

  • Write significantly less code
  • Have consistent data validation on client and server
  • Use an additional layer of abstraction and therefore less vendor lock-in

Today I’m happy to announce that heliosRX will be made open source under MIT license. I hope that it will help developers to write real-time web applications in significantly less time and with significantly less boilerplate. It will allow you to define the structure necessary to write web applications that scale.

What is heliosRX?

The basic idea behind heliosRX is:

You describe your data structures by providing a schema once. Based on that schema heliosRX will generate a client (with automatic client-side validation) and a server ( = security rules).

For the client you’ll get:

  • A straight forward CRUD API
    (add(), subscribeNode(), update(), remove())
  • Automatic input validation
    (better error messages during development, automatic user input validation)
  • Fully reactive state management — no Vuex needed
    (although heliosRX currently uses a Vuex store internally)
  • Automatic type conversion for timestamps to moment-js
    (Realtime Database has no native type for dates)
  • Useful extensions of the API, like easy sorting of objects (reorder()), automatically generated keys for v-for

For the backend you’ll get:

  • Automatically generate Security Rules based on the schemata
  • The same codebase, which can be recycled for Cloud Functions, which gives you the exact same API on the backend

Imagine data is changed on the server. Usually, you want to update your local state management, which then triggers a re-render of your templates. heliosRX provides the missing link between Firebase and Vue. While there are other libraries like vuexfire, that inspired heliosRX, from my experience there are certain limitations when things get bigger.

Consider the following simple example:

const taskModelDefinition = {
  schema: {
    fields: {
      title:     { type: 'String', required: true },
      createdAt: { type: 'ServerTimestamp' },
      isDone:    { type: 'Boolean' },
    }
  }
};

export const task = new GenericStore(
  '/user/{userId}/task/*', // This is where the data is stored in RTDB
  taskModelDefinition );

You define where your data is stored and what the data looks like. Of course, you can still nest your data and get all the benefits of a NoSQL database, this is just a simple example.

heliosRX provides a CLI which can generate security rules (in the bolt format), with:

$> helios rules

type Task {
  title:     String
  createdAt: ServerTimestamp | Null
  isDone:    Boolean | Null
}

Now a simple To-Do list would look like this:

<template>
  <ul>
    <li v-for="task in tasks.items" :key="task.$key">
      <input type="checkbox" @input="onCheckTask( task )">
      {{task.title}}
      <a href="#" @click.prevent="onDeleteTask( task )">del</a>
    </li>
    <input v-model="title" />
    <button @click="onAddTask" />
  </ul>
</template>

<script>
export default {
  data() {
    return {
      title: ""
    }
  },
  computed: {
    tasks() {
      return this.$models.task.subscribeList();
    }
  },
  methods: {
    onCheckTask( task ) {
      task.isDone = !task.isDone;
      task.save();
    },
    onAddTask() {
      this.$models.task.add({
        title: this.title
      });
    },
    onDeleteTask( task ) {
      task.remove();
    }
  }
}
</script>

heliosRX takes care that the template will rerender, by providing a reactive data model (tasks). In the background it creates a subscription to the database. If the data changes, the models internal data will get updated.

On top of that heliosRX mirrors the Realtime Database structure to a local Vuex store. This means you can create as many models as you want, they all point to the same data source and are therefore always consistent.

Also, let’s say you already synced the user path (/user/{userId}/) before subscribing to the task list that is stored within the user (/user/{userId}/task/{taskId}). heliosRX will automatically create a model based on the already existing local data, without making a new server request.

Whats next?

There are still a few major things I want to attack in the next few months:

  • Extendable API for plugins and custom backends
    (a GraphQL backend would be great!)
  • Reduce package size to < 50 kB
  • Vue 3.0 support
  • Typings for Typescript
  • More documentation and examples, especially on best practices/recipes

Try it and give feedback

heliosRX is available now and you can install it with:

yarn add heliosrx
# - or -
npm install heliosrx

Also check out the Documentation, especially the Intro Tutorial.

There is a lot of Gotchas when working with Firebase especially when writing Security Rules, the documentation has a growing collection of lessons learned and small tips, which I hope will help you to navigate around typical Realtime Database issues.

Examples

If you’re looking for a basic example, please have a look at:

For a more comprehensive example please check out:

Let me know if you have any suggestions, improvements or if you encounter any bugs.

Thanks for reading 👋

Want to stay tuned? Follow heliosRX on Twitter!