Getting Started

At first you should launch the container with Hub.

When it started you can use API to send events to manage the dashboard.

Open the dashboard http://localhost:6361 and let's use any of the following tools to send the event. The API address is http://localhost:1636/data.

Web browser

Yeah! It's possible to send event to the dashboard using an ordinary web browser with a plain GET request. To do that you should send actions in the query string format.

The following actions creates a board with my-board id and "My Board" title:


When it's created we can set a value using the set action:


It adds pair to the board: "My Key" that has "My Value" value.

Bash + Curl

To send data using curl you should send actions using a PUT request:

curl -X PUT --data-binary @- http://localhost:1636/data << Ri
!my-board:create type=board title="My Board"
!my-board:set key="My Key" value="My Value"

In the script above we call the curl and forward data from stdin to the API endpoint. Ri! is the terminal sequence to end the input stream. You can use any sequence you want.

When you run that command you the block with the board, key and value will immediatelly appeared on the dashboard.

The alternative way to send data to use POST request with an action in JSON format:

curl -X POST --data \
 '{"id": "my-board", "action": "set", "parameters": {"key": "My Key", "value": "My Value"}}' \

Grep + Sed

You can also use grep or sed (or other tools) to prepare the data using pipes. For example, let's send the current date value to the board:

date | sed 's/^\(.*\)$/!my-board:set key="Time" value="\1"/g' | \
  curl -X PUT --data-binary @- http://localhost:1636/data

You can even add some aliases to your shell to send interesting data to your dashboard like stats of usage of drive, terminal, or some diagnostics info, etc.


Using RillRate with Python is super easy. The following Python script creates a board and adds a value to it:

import requests

def ri(flow_id, action, **parameters):'http://localhost:1636/data', json = {
        "id": flow_id,
        "action": action,
        "parameters": parameters,

ri("py-board", "create", type="board", title="Py Board")
ri("py-board", "set", key="My Key", value="Py Value")

In the code above we also created a helper function to send actions.


You can send data even from a script in the browser using the fetch function:

async function ri(flow_id, action, parameters) {
    let payload = { id: flow_id, action, parameters };
    await fetch('http://localhost:1636/data', {
        method: "POST",
        mode: "no-cors",
        body: JSON.stringify(payload),

async function main() {
    ri("js-board", "create", { type: "board", title: "JS Board"})
    ri("js-board", "set", { key: "JS Key", value: "JS Value"})



In the example below we created a function to send data to the dashboard. But keep in mind that you should make sure that you have created a block before sending data to it. That's the reason why we used await here:

const axios = require('axios');

async function ri(flow_id, action, parameters) {
    let payload = { id: flow_id, action, parameters };
    await'http://localhost:1636/data', payload);

async function main() {
    await ri("js-board", "create", { type: "board", title: "JS Board" });
    await ri("js-board", "set", { key: "JS Key", value: "JS Value" });



In this example we need the following dependencies (add them to Cargo.toml file):

name = "rillrate-demo"
version = "0.1.0"
edition = "2021"

anyhow = "1.0.45"
reqwest = { version = "0.11.6", features = ["json"] }
serde = { version = "1.0.130", features = ["derive"] }
tokio = { version = "1.14.0", features = ["full"] }

Let's declare Ri client that will send data to the dashboard:

use anyhow::Error;
use reqwest::Client;
use serde::Serialize;
use std::collections::HashMap;

struct RiAction<'a> {
    id: &'a str,
    action: &'a str,
    parameters: HashMap<&'a str, &'a str>,

struct Ri {
    endpoint: String,
    client: Client,

impl Ri {
    fn new(endpoint: &str) -> Self {
        Self {
            endpoint: endpoint.into(),
            client: Client::new(),

    async fn action(&self, id: &str, action: &str, params: &[(&str, &str)]) -> Result<(), Error> {
        let action = RiAction {
            parameters: params.iter().cloned().collect(),

It uses reqwest crate and just send POST request to the server. Now we can use it to declare blocks and send our data:

async fn main() -> Result<(), Error> {
    let ri = Ri::new("http://localhost:1636/data");
        &[("type", "board"), ("title", "rs board")],
        &[("key", "rs key"), ("value", "rs value")],


You can use other languages and tool that can send HTTP requests in JSON format. We, in turn, will add more examples soon.

"Live Dashboard in 5 Minutes" weekly digest Subscribe