Inspiration

As part of our burgeoning sustainability management task force (and subsequently, permanent team), we were looking at various aspects of how to make sustainable choices more fun. Gamification emerged as a strong contender, so the idea to create a sustainability game was born.

Historically, there are two other similar games (albeit with differing specific aims) at Seibert Media: One in regards to health (dubbed "highway to health"), and another helping with onboarding (collecting stars on an intergalactic cruise).

Also, for creativity, who can say no to John Cleese on Creativity Management?

What it does

There's two main parts to the game. Both are macros which can be embedded on any page.

One is a game macro which lets you complete challenges from a list. Completing challenges earns you carrots (points). The game tracks the points in each section and turns green once sections are completed. There's also different levels. While sections are enabled over time in each level, the idea is that any given level is only available for a certain time, after which it is locked and no more points can be earned.

Why would you want to earn points? Well the second macro packaged in this app is a leaderboard which displays the highscores within your Confluence Cloud instance. Strive to be the greenest!

Additionally, there are badge macros, both for the total carrot score of the company, as well as for individual users, where they can show off their achievements.

How we built it

With Forge, of course! We used our colleague Julian Wolf's template for Forge apps. After that, we converted it to TypeScript (we'll likely publish that as a template as well) and created the macros as well as a few functions for handling persistence.

Challenges we ran into

Saving scores is somewhat simple with Forge storage API - but retrieving and especially aggregating them - while possible - proved more difficult.

What we came up with is this: While we save a game state object on a key called gamestate#<player id>, we have to save individual challenges directly in that object (again, as key value pairs) so we can then iterate over the constituent partial keys when regenerating state in the app.

Now that may seems overly flattened when we can entirely dictate what state objects should look like - until you factor in that there's currently very limited access to aggregates of these states. So we had a choice:

  • Either save the total score every time an update hits - which is not guaranteed to converge because Forge's storage API currently gives no atomicity and transactional guarantees.
  • Or try to somehow calculate the missing data. Since the lookup process described above takes quite a number of cycles, we didn't want to do that for every state item and every time the leaderboard is viewed. Also, server side functions have harsh run time restrictions.

For now, we settled on a compromised second option: We page the leaderboard results out and have the client fetch multiple pages if necessary. It then has all data it needs to properly calculate and then display the high scores itself.

This will probably not scale into larger instances. Depending on how Forge develops we may need to use third party services to either save data or at the very least as cache.

Accomplishments that we're proud of

Let's see... it was pretty cool (and thanks to Forge surprisingly easy) to rush an app out the door within what amounts to a few days of actual development time. We found a good compromise for our storage solution, all within the same ecosystem. Better do the Carrots looks and feels pretty good. And maybe most important of all: It's a clear indicator what's possible and that we can implement both of our important internal use cases (onboard and sustainability) using this app skeleton going forward.

What we learned

While Forge isn't quite there yet (depending where you look), it's already pretty cool to use and deploy. It's definitely very worth considering when planning to implement many use cases on Atlassian's cloud.

There's a bunch of error messages that iframes and other security tech present in forge tunnel simply swallow - so be ready to either look very closely, or - much preferred - develop with as much TDD/BDD as you can.

While we usually prefer TypeScript over JavaScript, there were initially some challenges with typings. In the end, some were resolved over the course of the CodeGeist by Atlassian publishing missing declarations, but others we had to type ourselves; another testament to the fact that not everything is 100% production ready with Forge.

What's next for Better do the Carrots

Some of the time-based features are as of yet incomplete. We're looking forward to adding more challenges to the app. And ultimately, we may allow Confluence Cloud admins to opt in to sharing their instance's average carrot score per user with the world and take part in a global leaderboard.

If there's enough interest, we may also generify this app into a challenges app where you can configure your own challenges.

Share this project:

Updates