Skip to main content

· 3 min read
Tyson Cadenhead

Milo is my oldest son. He is 12 years old and he is non-verbal. Since his autism diagnosis 10 years ago, we have tried just about every augmentative and alternative communication (AAC) iPad app available to help him to communicate with us.

A couple of months ago, I was setting up some buttons on TouchChat when I saw that there was an option to add a WebHook as a button action. Right away, my wheels started turning. I have a Vestaboard mounted on the wall in my upstairs home office. What if Milo could send me messages during the day from his "talker"?

I started by adding a few buttons with messages that Milo could send to our Vestaboard.

Once I started digging into the WebHook implementation in the TouchChat app, I realized that they did not support custom headers for the webhooks, so I knew I was going to need to spin up a simple service to send messages to my board with our Read/Write API

I created an extremely simple Ampt application on my personal account to make the requests to the Read/Write API. TouchChat could accept a JSON payload for the POST body. I set up my service to expect a hard-coded token using the Ampt params package and a text string with the message to be sent.

Here is the entire codebase for the Vestaboard TouchChat application:

import { http } from "@ampt/sdk";
import express from "express";
import cors from "cors";
import bodyParser from "body-parser";
import fetch from "node-fetch";

const app = express();

app.use(cors());
app.use(bodyParser.json());

app.post("/", async (req, res) => {
if (req.body.token !== process.env.TOKEN) {
return res.status(401).send({
message: "Unauthorized",
});
}

await fetch("https://rw.vestaboard.com/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Vestaboard-Read-Write-Key": process.env.VESTABOARD_KEY,
},
body: JSON.stringify({
text: req.body.text,
}),
}).then((res) => res.json());

res.send({
success: true,
});
});

http.node.use(app);

Finally, I updated all of the button actions in the "Vestaboard" screen I created on TouchChat. I setup a WebHook with a custom message for each button.

In a short amount of time, I had a completely working prototype that allowed Milo to send me messages anytime. The idea is that we could add more messages over time as his vocabulary and needs expand. Adding new messages would not require an update to the Ampt service, because the message itself is coming from TouchChat.

Here is one of the messages that Milo can send to the Vestaboard:

I realize that this is a one-off use-case that may be a bit esoteric for most Vestaboard developers, but this basic concept of using the Read/Write API with other applications' WebHooks can apply pretty universally. If you want to dig in, the source code is hosted on GitHub

This example may not change the world, but it might change our family. Vestaboard is empowering Milo to communicate in a new way!

· 4 min read
Tyson Cadenhead

Ampt is a Serverless framework that inverts the infrastructure as code paradigm to an even more intuitive idea of infrastructure in code. This allows you to quickly create scalable applications without the overhead of provisioning resources.

As of today, Ampt is officially launching to the public. We have been using Ampt at Vestaboard for several months now to simplify our infrastructure and as the backbone for many of our new Vestaboard+ features. The launch of Ampt is an excellent opportunity to showcase how simple it is to schedule and automate Vestaboard messages on a cadence.

Get Started with Ampt

The first thing to do is sign up for your own Ampt account. From there, you just need to install the Ampt CLI by running:

npm i -g @ampt/cli
ampt

Initially, this will prompt you to log in to your Ampt account. After you have, you can select "Create new app" from the CLI and choose a starter template. For our purpose, we'll go with "TypeScript API (Express)." We can name the app whatever we want, so how about something like "vestaboard-custom-clock" and we're all set. Ampt will spin up a new application and even start up a developer sandbox for you that is a fully operational serverless project.

In the root of your newly created project, there will be an index.ts file. Go ahead and delete all the code in there and import the task from Ampt. We'll use that to schedule a task. To make sure it's working as expected, you can just drop in a console.log. Let's make a task that logs every 1 minute:

import { task } from "@ampt/sdk";

task("vestaboard-clock", async (event) => {
const timestamp = `${new Date().toDateString()} ${new Date().toLocaleTimeString()}`;
console.log(`It is ${timestamp}`);
}).every("1 minute");

This will log every 1 minute with something like:

It is Mon Sep 18 2023 1:34:16 PM

It is important to note that you can also use tasks with a cron expression or to run a task once at a specific time. If you want to explore more options, check out the Ampt documentation.

Send a Message to your Vestaboard

Now, we just need to send a message to your Vestaboard when the scheduled task is fired. The first step is to enable the Vestaboard Read/Write API in order to get your token.

Ampt has a dashboard at https://ampt.dev/ where you can query data, set environment variables, see production logs and more. Since the Read/Write API token is a secret, you don't want to store that in your code, but instead, you'll want to add it as an environment variable in the "parameters" tab of the Ampt dashboard. Let's call it VESTABOARD_TOKEN. You can access it in code using the params export:

import { task, params } from "@ampt/sdk";

task("vestaboard-clock", async (event) => {
const VESTABOARD_TOKEN = params("VESTABOARD_TOKEN");
const timestamp = `${new Date().toDateString()} ${new Date().toLocaleTimeString()}`;
console.log(`It is ${timestamp}`);
}).every("1 minute");

Now, we just need to install a fetch package:

npm i fetch@2 --save

and make a request to the Read/Write API with our token:

import { task, params } from "@ampt/sdk";

task("vestaboard-clock", async (event) => {
const VESTABOARD_TOKEN = params("VESTABOARD_TOKEN");
const timestamp = `${new Date().toDateString()} ${new Date().toLocaleTimeString()}`;

await fetch("https://rw.vestaboard.com/", {
body: JSON.stringify({ text: `It is ${timestamp}` }),
headers: {
"Content-Type": "application/json",
"X-Vestaboard-Read-Write-Key": VESTABOARD_TOKEN,
},
method: "POST",
});
}).every("1 minute");

That's it. With just a few lines of code, you've set up a scheduled task in Ampt that automates your Vestaboard. Imagine the possibilities!

If you'd like, you can clone our repo on GitHub with a full working example.

· 2 min read
Tyson Cadenhead

I came on full-time at Vestaboard about a year ago and started the process of discovering what we already had as well as taking part in building a vision for what the future of Vestaboard engineering will look like. Over the past year, we've built up our internal engineering team and focused heavily on new feature development as well as handling ongoing bug fixes and tech debt.

Our mantra has been to simplify the Vestaboard platform and to make it more scalable and resilient.

The truth is, our flagship product is very simple: we have a beautiful board that displays messages when you send them.

In the process of revamping our documentation, and in rebooting the Vestaboard Developer Community, we hope to bring back the fun and simplicity that makes Vestaboard so appealing as a software engineer in the first place.

You may notice that the new Subscriptions API is simpler than the old version. This is in part to stop exposing internal data structures that get in the way of quickly working with our APIs. It is also to dial things back and start to understand what endpoints provide value to you, the developer, so we can harden them and make them work better for everyone going forward.

In the coming weeks, we will be adding more content here. We will be creating quick-start guides to simplify the process of sending messages. We will provide solutions we've used and solutions we've seen in the wild that make building integrations and tasks that send messages easier.

If you haven't already, please join our Slack community to stay up to date on everything and we would absolutely love any feedback on how we can make the developer experience better.