Integrating Val Town with tana
Tags: productivity, automation, javascript, socialmedia
Published: 2023-07-21 12:33:53

## Problem Statement

I have been using [tana](https://tana.inc/) for knowledge management and as a [Kanban](https://en.wikipedia.org/wiki/Kanban) board for tracking work. From past experience, I've learned that I am motivated by productivity metrics. Therefore, I implemented two [tana commands](https://help.tana.inc/tana-commands.html) in order to track the work that I complete and receive notifications on my productivity stats.

## Solution Overview

To accomplish this task, I created three [tana](https://tana.inc/) commands. The first command writes the name of the current node to an [Airtable base](https://support.airtable.com/docs/airtable-bases-overview). This base includes the name of the task (from the node name) and the date it was completed.

The second command calls a val on [Val Town](https://www.val.town/). The val is a script that counts the tasks completed today, and the tasks completed yesterday, and produces a message like this: *You have completed ${todayCount} tasks today, compared to ${yesterdayCount} yesterday.*

The third command is a "Supercommand" that simply runs the first and second commands in sequence.

All of my tasks are tagged with `#outcome` and the final step was to add the command to the `#outcome` tag so that I can click on it when I complete a task, the task is then written to Airtable, and a notification pops up showing today's productivity stats.

## Writing To Airtable

To create a new command, you simply type the name into the node text and run the "Convert to command node" command. Then you nest tana commands beneath it, like this:

![Tana command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kb7vx6p99dzmnogp4rxf.png)

You can see in addition to calling the Airtable API, I'm also setting the status to "done". This will make more sense when you see the finished product below.

## Creating The Val

[Val Town](https://about.val.town/) is a website where you can write snippets of JavaScript or TypeScript. It has social features, and one cool thing about it is that your scripts are callable via API, making it perfect for integration with Tana. In Val Town I set secrets for my Airtable and Pushover API keys, then I reference them in my private val. Although there is a [public val for calling Pushover](https://www.val.town/v/meatcar.pushover) I decided against using it, because I don't feel safe calling public vals with secret data, due to the risk that a val author could rewrite the code. This is [discussed here](https://docs.val.town/permissions#2b0b91b14262419a8e6ea1903ad2c08f) and will be solved in the future.

Here are the contents of my val which performs the metrics calculation and calls Pushover:

```JavaScript
async function get_work_stats() {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const yesterday = new Date(today);
  yesterday.setDate(yesterday.getDate() - 1);
  const options = {
    method: "GET",
    headers: {
      authorization: `Bearer ${@me.secrets.airtable_api_key}`,
    },
  };
  const response = await fetch(
    "https://api.airtable.com/v0/appzwhnlnPyQYXO5f/Tasks",
    options,
  );
  const data = await response.json();
  let todayCount = 0;
  let yesterdayCount = 0;
  for (let record of data.records) {
    const recordDate = new Date(record.fields.Created);
    recordDate.setHours(0, 0, 0, 0);
    if (+recordDate === +today) {
      todayCount++;
    }
    else if (+recordDate === +yesterday) {
      yesterdayCount++;
    }
  }
  const message =
    `You have completed ${todayCount} tasks today, compared to ${yesterdayCount} yesterday.`;
  const po = await fetch("https://api.pushover.net/1/messages.json", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      token: @me.secrets.pushover_app_key,
      user: @me.secrets.pushover_user,
      message: message,
    }),
  });
  const poData = await po.json();
}
```

Note this val doesn't return anything, because we're interested solely in the side-effect of the API call to Pushover.

## Calling the Val Town API From Tana

We're almost finished! Now that the val is available, this is how I'm calling it from Tana:

![Tana call val](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wvlsie8mha06g2ayrbmi.png)

## Putting It All Together

Now that I have my Tana commands for writing task completion status to Airtable, and another command to pull metric status and publish it to Pushover, I create a Tana Super Command that runs both commands in sequence, and give it an emoji name so that it looks nice during day-to-day usage:

![Super command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/te3hle5b41x8akdkqxme.png)

All my tasks are tagged with `#outcome` so the last step is to enable this command for this Super Tag:

![Tana advanced command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2si1veegmmiay29n68bp.png)

## Demo

Now when I check off my tasks, I click the green checkmark instead of the checkbox on the left. See this example:

{% embed https://www.loom.com/share/1fc1f9d0de054f07afaaa3eb32901313 %}


The task is saved to Airtable and I receive a notice on my phone.

![iPhone notification](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p30wih67d9mp3gvz53yn.jpeg)

### Next Steps

I'm going to continue building out this workflow to include more meaningful metrics. In addition to "today vs. yesterday" I also like to see today compared to the same day last week. I also want to add insights, for example positive reinforcement when I've exceeded the weekly total from last week. Fortunately this system is extensible to include the metrics that matter most.

Lastly, I will end up switching from Pushover to a [Telegram Bot](https://core.telegram.org/api). Telegram has an incredible API, bots are free to run, and Telegram has native clients for all the major platforms.