Muut IO is a unique service that allows developers to build conversational applications like commenting or forums. This article provides you with a basic understanding of how to create applications with Muut IO.

One of Muut IO's most powerful features is custom metadata. You can store any kind of data (strings, numbers, arrays, and complex objects) to threads, and then query those threads based on the metadata values. This enables you to build wildly different applications, such as:

  • Ticket tracking by storing "assignedTo" and "solved" metadata
  • Geotagging by storing user's coordinates
  • Micro commenting by storing the location of comments on the page
  • Timeline commenting to audio and video progress bars
  • Any sort of tagging: "techno", "alternative", "ambient", "house" etc...
  • Emotional counters: how many people loved the post? How many celebrated?

IO client

Muut IO is a server side application with a simple API. You can interact with it on the server side using your favorite REST library.

You can also build the application solely utilizing the client with IO client library, which lets you quickly put together a social app while Muut IO takes care of the hard stuff, like connection and session management.

This tutorial focuses on the client side.


In this tutorial, we'll build a simple demo with all the essential features common to all conversational applications.

The demo uses Riot JS, a micro framework we created for the job because that's what I'm personally most comfortable with, and it has a simple, easy to follow syntax for the purposes of this demo. You can obviously use the tool of your choice, such as React.

We'll be focusing on the general concepts as well as the IO client.

Rendering the application

Muut IO application starts with a muutio call as follows:

muutio(query, function(data) {
  // render the data

Rendering the app

The query can be as simple as the project name (i.e., "acme"), or a complex query with metadata and sorting parameters. The callback function on the second argument will receive the returned data, which contains all the information for rendering the application.

The way you render this data depends on your application — in fact, that is your application, its core design. The data contains crucial information, such as discussion categories, administrators, current online users, as well as the discussion threads that match your query.

Since we use Riot for rendering the UI, our muutio call looks like this:

muutio("playground", function(data) {
  riot.mount('muut-demo', { data: data, api: this })

We pass the data as well as the Muut IO API to the application so we can interact with the server. This call is made in the index.html file file of our single page application.

Loading more data

Only the most recent replies and threads return in the data, so you need to perform additional calls to receive more data:

  • threads call to load older threads than ten most recent ones.
  • threadExpand to receive the latest replies and the seed post for individual threads. Threads are initially collapsed for anonymous users. For authenticated users, the system remembers which threads are collapsed and which aren't.
  • moreReplies to load more replies for individual threads.
  • more to receive the rest of the (longer) body text for individual replies.

You can pass the expand_all parameter for the muutio call if you want the threads to be collapsed initially. For example:

muutio({ path: '/playground', expand_all: true }, function(data) {



Before the current user can do anything besides browsing and reading, they must authenticate. This can happen in two ways:

  1. Using Muut IO authentication popup where the user enters Muut username and password.

  2. Using a technique called "federated id" with signed authentication data so you can use your user database for authentication.

In this demo, we use the dialog, but you can learn more about federated id here.

Authentication dialog

The authentication dialog is a web page under that is opened in a new window with correct parameters using secure SSL protocol.


When the user authenticates by signing up as a new user or logging in with existing password, the application receives a "login" event. After this event, all the successive calls from the user are authenticated.

The dialog is opened with a api.openLogin() call. In our demo we simply type:

<a if={ !logged } onclick={ opts.api.openLogin }>Log in</a>

And wait for the "login" event.

Listening to events

Events are what turn an application into a real-time application. They allow you to update the UI automatically without the user doing a thing. Muut IO sends many kinds of different events during the operation. For example, the above "login" event is caught as follows:

api.on('login', function(path) {
  // user is authenticated

You want to listen to at least "thread" and "reply" events to know when others have posted new content.

Reloading the UI

When the client receives "login", "logout", or "reconnect" events you should reload the application with new data because authenticated data is very different from anonymous data, and if the user is offline for long, the data might have changed a lot during that time. Here's how you do that:

api.on('login logout reconnect', function() {

  // load new data'init', { path: '/playground' }, function(new_data) {

    // re-render the UI with new data




Behind the scenes, the IO client uses EventSource for the real-time events and falls back to long polling on older browsers.

Posting data

After a successful login, the user will be allowed to post new content, as well as do other actions (like, spam, unspam, watch) for posts. Here's how you create a new thread:'threadCreate', {
  body: ['First paragraph', 'Second paragraph'],
  path: '/playground/general',
  title: 'My test thread'

}, function(key) {

  // key is a human readable ID for the thread used
  key == 'my-test-thread'


All thread related calls such as "threadExpand" require the thread's path as an argument, which would be "/playground/general#my-test-thread" for the thread we created above.

Other clients will receive a "thread" event and can render the newly posted thread in real-time.

Using metadata

After the basics are in place, it's time to add your custom logic by utilizing metadata. You can save any kind of data to threads, then filter the threads based on the data.

In our demo application all the user-written tags (prefixed with #- character) are saved as metadata:'threadCreate', {
  meta: {
    public: {
      str_tags: ['test', 'random']
  body: ['First paragraph', 'Second paragraph'],
  path: '/playground/general',
  title: 'My test thread'

}, function(key) {

  // key is a human readable ID for the thread used
  key == 'my-test-thread'


After you have stored some metadata, you can start filtering threads. For example:'init', {
  query: {
    filter: { 'meta.public.str_tags': ['random', 'food'] },
    path: '/playground/',
    version: 1
}, function(data) {

  // received filtered data


Cool, huh? Take a moment and think about what you could do with metadata. The possibilities are endless!

Summing up

Muut IO is a unique service that provides functionality not present on any other service. You can get up and running in a fraction of the time that it otherwise could have taken — possibly months, or even years. And you will never experience scalability issues no matter what your load is.

Building the infrastructure yourself is often the hardest part of building a service. Muut IO lets you get to market faster with a better product.

Our API is famously fast and performant, and you'll experience response times that are far below the industry average.

— Tero Piirainen

Get started with Muut IO

Previous Post