I Built a Google Calendar Add-on. Here's What I Learnt
Tags: tinyproject, googleappsscript
Published: 2023-11-10 00:03:16

---
title: I Built a Google Calendar Add-on. Here's What I Learnt
published: true
date: 2023-05-02 00:00:21 UTC
tags: TinyProject,GoogleAppsScript
canonical_url: https://jerrynsh.com/i-built-a-google-calendar-add-on-heres-what-i-learnt/
---

 ![I Built a Google Calendar Add-on. Here's What I Learnt](https://jerrynsh.com/content/images/2023/04/home_1280_720.png)

I made [Tournacat](https://tournacat.com/), an add-on that syncs upcoming Esports schedules of tournaments to Google Calendar. Two months later, Tournacat has garnered 4 paid users and is slowly growing.

In this post, I will share my experience building Tournacat using various technologies including Cloudflare Worker, Hugo, and Google Apps Script.

Along the way, I encountered some interesting challenges and learned valuable lessons. Specifically, I want to share my anecdotal experience with issues I encountered while developing the Tournacat add-on using Google Apps Script.

## Why Did I Make Tournacat

![I Built a Google Calendar Add-on. Here's What I Learnt](https://jerrynsh.com/content/images/2023/04/month_1280_720.png)
_A "Month" view of upcoming Esports schedules in Google Calendar._

Tournacat [started as an idea from D2GCal](https://jerrynsh.com/sync-dota-2-esports-matches-to-your-google-calendar/), a link to a Google Calendar featuring upcoming [Dota 2](https://www.dota2.com/) tournaments available for purchase on [Gumroad](https://jerrynsh.gumroad.com/l/d2gcal).

I built Tournacat out of the frustration of missing out on big Dota 2 matches. I was tired of constantly scouring the internet to find out when my favorite matches were happening.

As an avid Esports fan, I knew there had to be a better way (_cliché I know_). So, I started building Tournacat for my own use.

Today, Tournacat has grown to support major Esports titles including _Counter-Strike_, _Dota 2_, _LoL_, _Valorant_, _Overwatch_, [and more](https://tournacat.com/faqs/#what-games-and-esports-titles-are-covered).

## Why Google Calendar

I use Google Calendar extensively in my daily life, from scheduling meetings to keeping track of personal events. So, having an Esports schedule alongside everything in one place is a huge plus.

With Tournacat, you can just [install the add-on to your Google Calendar](https://workspace.google.com/marketplace/app/tournacat/1041160187344) and let it work its magic. It's a seamless solution that integrates perfectly with Google Calendar.

![I Built a Google Calendar Add-on. Here's What I Learnt](https://jerrynsh.com/content/images/2023/04/schedule_1280_720.png)
_A "Schedule" view of upcoming Esports schedules in Google Calendar._

### Existing Solutions (Calendars)

I've been on the lookout for a solution like Tournacat for years. I've tried all sorts of public Esports calendars in the past, but they always fell short in one way or another.

Either the author of the calendar stopped updating it, or it was just an unreliable source that was prone to human error. It got to the point where I gave up hope of ever finding a calendar that actually worked.

## Tech Stack

Tournacat is built using a variety of tools and technologies. The tech stack includes:

- Frontend — [Hugo](https://gohugo.io/)
- Backend — [Cloudflare Worker](https://workers.cloudflare.com/)
- Add-on — [Google Apps Script](https://developers.google.com/apps-script)

### Hugo

Hugo is a [static site generator](https://www.gatsbyjs.com/docs/glossary/static-site-generator/#what-is-a-static-site-generator) that I used to create the [Tournacat website](https://tournacat.com/). I decided to use Hugo for a couple of reasons.

First, I'm not particularly skilled in front-end development, so I wanted to use a static site generator that would allow me to use pre-built themes without having to write much front-end code myself. Hugo fit the bill perfectly in this regard.

Second, Hugo is known for its speed and ease of use. I wanted to be able to iterate quickly and not have to spend a lot of time fussing with my site's performance or configuration. Hugo's documentation and tooling made it easy to get up and running quickly. With that, I was able to focus on building out the content for Tournacat’s website rather than worrying about technical details.

I then hosted the website on [Cloudflare Pages](https://pages.cloudflare.com/). Using Cloudflare Pages allowed me to keep costs down, as I didn't need to pay for expensive hosting services.

### Cloudflare Worker

For the backend, I decided to go with Cloudflare Worker. Cloudflare Worker is a [serverless computing](https://www.cloudflare.com/learning/serverless/what-is-serverless/) platform that allows you to run JavaScript code [on the edge](https://www.cloudflare.com/learning/serverless/glossary/what-is-edge-computing/).

To make my life easier, I decided to build the backend server Tournacat on top of a framework — Worktop, a lightweight Cloudflare Worker web framework that simplifies the development of APIs using TypeScript.

[

GitHub - lukeed/worktop: The next generation web framework for Cloudflare Workers

The next generation web framework for Cloudflare Workers - GitHub - lukeed/worktop: The next generation web framework for Cloudflare Workers

 ![I Built a Google Calendar Add-on. Here's What I Learnt](https://github.com/fluidicon.png)GitHublukeed

 ![I Built a Google Calendar Add-on. Here's What I Learnt](https://opengraph.githubassets.com/e44527f3b710cb8af5863f9ce7f184d99eadd12dbf236788cf1669c4649e2a2d/lukeed/worktop)
](https://github.com/lukeed/worktop)

Given the opportunity to start over, I would consider using [Hono](https://hono.dev/) instead, as it appears to be more actively maintained [on GitHub](https://github.com/honojs/hono).

My decision to choose Cloudflare Worker was based on my comfort level with it, [having done several previous projects](https://jerrynsh.com/tag/cloudflare-worker/) with it. The developer experience was nothing short of amazing, and deployment was easy. Furthermore, it was [affordable with a generous free tier](https://developers.cloudflare.com/workers/platform/limits/#worker-limits).

While the performance was impressive, it was not the main reason why I picked it.

### Google Apps Script

[Google Apps Script](https://www.google.com/script/start/) is the core technology behind the [Tournacat add-on](https://workspace.google.com/marketplace/app/tournacat/1041160187344). It is a scripting language based on JavaScript that allows you to extend and automate Google Workspace products like Google Calendar, Sheets, and Drive.

While building Google Workspace add-ons is possible with [other coding languages (runtimes)](https://developers.google.com/workspace/add-ons/guides/alternate-runtimes), I decided to go for Google Apps Script anyway due to convenience. Frankly, I never thought that I’d be impressed at how simple it is to build a workspace add-on!

Do keep in mind that it does come with [some limitations and quotas](https://developers.google.com/apps-script/guides/services/quotas).

## Navigating the Bumps

Creating a Google Workspace add-on is relatively straightforward. The [add-on tutorial](https://developers.google.com/apps-script/add-ons/cats-quickstart) provided by Google Workspace is pretty easy to follow.

In short, It took me a day to figure out most things and about a week to get the add-on approved and published on [Google Workspace Marketplace](https://workspace.google.com/marketplace).

### Advantages

1. One of the pros of using Google Apps Script is that it literally cost nothing to run.
2. Since it uses JavaScript, it's easy for most developers to pick up and start working with.

### Challenges

1. Although Google claims that [Apps Script is now supported by the V8 runtime](https://developers.google.com/apps-script/guides/v8-runtime), it doesn't _actually_ support Promises or async-await ([Issue Tracker](https://issuetracker.google.com/issues/149937257)). Consequently, you may need to resort to [using workarounds like triggers](https://stackoverflow.com/a/59750451) (Stackoverflow references: [1,](https://stackoverflow.com/questions/31241396/is-google-apps-script-synchronous) [2](https://stackoverflow.com/questions/61578224/does-google-apps-script-v8-engine-support-promise)).
2. Pushing changes to the Workspace add-on is rather unorthodox. I noticed this when one of my users couldn’t get their time-based triggers to work properly after a new deployment. Turns out the “correct” way to update a workspace add-on is to **edit** a versioned deployment instead of creating a new one ([Stackoverflow reference](https://stackoverflow.com/questions/69294697/workspace-add-on-with-installable-calendar-event-trigger-stops-working-with-new/69300465#69300465)).

![I Built a Google Calendar Add-on. Here's What I Learnt](https://jerrynsh.com/content/images/2023/04/image.png)
_Edit a versioned deployment with "New version" to update a workspace add-on_

3. It has to respect the [limits set by Google](https://developers.google.com/apps-script/guides/services/quotas). However, it wasn't documented if the limits were shared across all add-on users cumulatively (_hint: it is not_).

4. Lastly, I came across an authentication-related issue (Stackoverflow references: [1,](https://stackoverflow.com/questions/65124449/trigger-error-were-sorry-a-server-error-occurred-while-reading-from-storage) [2](https://stackoverflow.com/questions/60442915/container-bound-script-getting-permission-errors-trying-to-run-functions-with-go)) when attempting to use Google Apps Script as a webhook to allow my users to automatically activate their subscriptions after payment. Some answers suggested [temporarily disabling the V8 runtime](https://stackoverflow.com/a/65124855) to fix this.

Despite these hiccups, Google Apps Script is a great platform to work with. It gets 90% of the job done very effectively and the last 10% is the challenges that I mentioned.

### Some Lessons Learned

1. **Use what makes you the most productive.** Don’t worry about picking the perfect tech stack that handles scale.
2. **Users couldn’t care less about your code.** Nobody except you cares about the fancy frameworks, design patterns, or architecture used.
3. **Keep your deployment simple.** This allows for fast iterations. While I could have gone all-in with AWS and set up a sophisticated Terraform setup, I realized that I would have taken more time to ship if I were to go this route.

## Closing Thoughts

I have always had the itch to build a micro SaaS. So, I decided to build one realizing that it wouldn’t make me rich or change the world. I simply enjoy building stuff that people want to use and money is the ultimate validation for that.

However, building a SaaS was not exactly what I thought it would be — keeping my head down and coding away. I needed to understand my users and their needs and learn how to market my product effectively.

I must admit, marketing is not something I truly enjoy. But, I realized that it's a necessary job that comes with building a product.

Overall, building Tournacat was a rewarding experience. Seeing Tournacat slowly grow and gain traction has been an exciting journey. I'm eager to continue on this journey and I look forward to what the future holds.