Bringing our Comic Relief Values to life with IoT, Amplify and Serverless

Peter Vanhee
Comic Relief Technology
4 min readDec 6, 2019

Seven values, from “Break down Barriers”, to “Have a sense of humour, always”, together with a wish from our director Charlotte to bring our values to life, proved to be enough inspiration to spend a fun afternoon hacking together a live values dashboard.

The idea? Put an Amazon Dash button on each card, make people vote for the value they’ll carry out throughout the day by pushing the button on the card when they enter the office, and display a live dashboard of “most voted values”.

While our dashboard certainly piqued the interest of colleagues, ranging from “this is cool!”, to mild curiosity, to “what the hell is this?”, we really did this as a fun exercise in turning a simple idea into an actual scalable product in a short time frame and using our familiar serverless stack.

Our seven Comic Relief Values.

Our tools

This is how we connected it all up:

  • Seven AWS IoT enterprise buttons we purchased and registered to our AWS account, with each button associated to one of our seven values.
  • A DynamoDB table to store all the votes
  • AWS AppSync, so we can use GraphQL to update our DynamoDB table and streams updates to the front-end using subscriptions
  • A Lambda function which connects the IoT button click and runs a GraphQL mutation update DynamoDB
  • A ReactJS front-end bootstrapped using create-react-app and using our Comic Relief component library.

Real-time values dashboard

The dashboard in action.

It takes approximate 3–4 seconds from button push to dashboard update, and most of that time is spent by the dash button connecting to the WiFi and sending the payload to the Lambda function, with <1sec to update DynamoDB and stream the updates to the front-end.

In real life.

To get some insight into usage, we hooked it up to Serverless dashboard which will send out alerts to Slack when there is lots of activity.

Using Serverless dashboard to get a bit of insight into button pushes.

How we built it

We used AWS Amplify, and one of the things that surprised me most is the speed at which we got this all running.

Architecture diagam.

First of all, let’s initialise our app

# Create a new react app
npx create-react-app cr-values
cd cr-values
# Initialize amplify
amplify init

Now, adding a GraphQL API is as simple as

amplify add api

The only input you need to give is the GraphQL schema, which in our case was really simple. We associate a random ID with a buttonType (any of the seven values), a clickType (single click, double click or long click), and a timestamp.

type ButtonPush @model {
id: ID!
buttonType: String!
clickType: String
created: AWSTimestamp
}

Amplify automatically handles the entire API creation, and generates GraphQL queries, mutations and subscriptions you can use in your ReactJs front-end.

Now, we need to connect button pushes to a GraphQL mutation using Lambda. The event contains which button was pushed, and the clickType. We then send this to GraphQL using the aws-appsync SDK.

const push = async (event, context) => {
const { placementInfo, deviceEvent } = event;

const mutation = gql`
mutation createButtonPush {
createButtonPush(input: {
id: "${uuid()}",
buttonType: "${placementInfo.attributes.buttonType}",
clickType: "${deviceEvent.buttonClicked.clickType}",
created: ${new Date().getTime()}
}) {
id
buttonType
clickType
created
}
}
`;

await graphqlClient.mutate({ mutation });
return {
statusCode: 200,
body: 'Button clicked',
}),
};
export default push;

For our front-end, we have a simple React component which uses the useEffect hook to run a subscription operation and store button pushes using useState so we can re-render our component.

const [newPushes, setNewPushes] = useState([]);useEffect(() => {
API.graphql(
graphqlOperation(subscriptions.onCreateButtonPush)
).subscribe({
next: (todoData) => setNewPushes(todoData.value.data.onCreateButtonPush)
});
}, []);

The actual code is a little more complicated, as we use another effect to run GraphQL list operation to populate initial state, and re-render upon changes of the newPushes.

And that’s all — we proved that with the right tooling it’s incredibly quick to build something useable. We’re excited about this tech stack (AWS Amplify is something I’ll personally explore a lot more going forward) and will certainly do a few more iterations with our colleagues.

Dashboard snapshot.

Massive thanks to Adam Clark and Gustavo Liedke for building this together in an afternoon and learning from each other, and Charlotte Hillenbrand for launching our Comic Relief values and providing us with the inspiration to build this.

--

--

Peter Vanhee
Comic Relief Technology

Passionate technologist. Founder and director @marzeelabs @weareserverless. ex-head of technology @comicrelief