Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App
Tags: tutorials, guides, feature, concepts
Published: 2020-11-03 22:03:24

---
title: Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App
published: true
date: 2020-11-03 10:56:41 UTC
tags: Tutorials,Guides,Feature,Concepts
canonical_url: https://blog.cotter.app/cotter-cloudflare-workers-google-calendar-api-build-a-serverless-calendar-booking-app/
---

 ![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/Cover.png)

During this pandemic, scheduling a meeting has become more important than ever, be it for a conference call, a consultation, or just a friendly chat.

In this guide, we'll explore how to use Google Calendar's API to make your own **calendar booking app** (yes, it's a platform, so other people can log in and share their own calendar link!).

![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/calendar.gif)<figcaption>Build a Calendar Booking App with Cotter, Cloudflare Workers, and Google API</figcaption>

### 👉 Try out the live demo!

[Calendar Booking App by Cotter](https://cottercalendar.herokuapp.com/)

### We'll use:

- [Cotter](https://www.cotter.app/) for logging in users and connecting to their Google Account.
- [Cloudflare Workers](https://workers.cloudflare.com/) as a backend that will call Google Calendar API.
- [Google Calendar API](https://developers.google.com/calendar/v3/reference) for booking time slots in your users' calendar.
- We'll also use React in this tutorial.

# Why Cloudflare Workers?
![Cloudflare Workers](https://blog.cloudflare.com/content/images/2019/06/442516AB-F97C-4725-B0A8-1F8157043B2C.jpeg)

[Cloudflare workers](https://workers.cloudflare.com/) allows you to deploy JavaScript code on Cloudflare's Edge network. This means you can write serverless code in Cloudflare workers and have it deployed across the globe. Your users will connect to the nearest Cloudflare network.

### What about a database?

Cloudflare workers offers a [Key-Value store](https://www.cloudflare.com/products/workers-kv/) that can keep consistent data across their locations. Note that currently, it's "eventually consistent" which means it might take some time (max 60s) for an update to be available globally.

### Why do we need a backend?

The biggest reason why we need a backend in this tutorial is that **we need a secure environment to store our API Secret Key** which is used to get Google's Access Tokens from Cotter.

**We don't need a database or a key-value store for our use case,** so Cloudflare Workers is perfect for deploying a simple backend code that authenticates your users and calls Google's API

# TLDR

To try it out right now, you can use our CodeSandbox and follow the steps below to set up the Cloudflare Backend:

**1. Create a project at [Cotter](https://dev.cotter.app/), then add Sign in with Google to your Login Form**

- [Follow these instructions to set up Google OAuth 2.0 Credentials and connect it to Cotter](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider/google-instructions). 
- Make sure you added `https://www.googleapis.com/auth/calendar` for the scope.
- Enable Google for your form: Go to Branding > Magic Link Form > click the checkmark to enable [Google Sign In](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider#setting-up-social-login-provider)
- Add Cotter's Login Form to your website

**2. Use this [CodeSandbox](https://codesandbox.io/s/cotter-calendar-bs7qb?file=/src/constants.js) to get the calendar-booking React App.** Update `src/constants.js` with your Cotter API KEY ID. You can also clone the project from the [Github Repo](https://github.com/cotter-code/calendar-booker).

**3. Setup Cloudflare Worker, make 3 workers with subdomains:**

- `checkconnection.YOURSUBDOMAIN.workers.dev`
- `createevent.YOURSUBDOMAIN.workers.dev`
- `disconnect.YOURSUBDOMAIN.workers.dev`

[Copy the code from our Github for your Cloudflare Worker](https://github.com/cotter-code/calendar-booker/tree/main/cloudflare).

**4. Enable Google Calendar API in your Google project**

Enable [Google Calendar API](https://console.developers.google.com/apis/api/calendar-json.googleapis.com) to the project that you used to create Google OAuth 2.0 Credentials.

# How it works

![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/Diagram.png)

Here's the outline of the things that we needed to do to build this platform:

- Users will be using "Sign in with Google" to get an access token from Google. This access token is accessible via [Cotter's API](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider/getting-access-tokens-from-social-login-providers).
- Make API endpoints at your Cloudflare Worker which would 1) call [Cotter's API](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider/getting-access-tokens-from-social-login-providers) to get the user's Google Access Token, and 2) call Google's API using that Google access token.

* * *

# Logging In

![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/image-1.png)

## Getting Google's Access Token via Google Sign In

To access Google's Calendar API, you'll need a Google Access Token for the user to modify their calendar. This means the user needs to connect their Google Account. Using Cotter as your authentication service, this can be done in 2 ways:

- **If the user logged-in using Google Sign In** , you can automatically access their Google Access Token by calling [Cotter's API](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider/getting-access-tokens-from-social-login-providers).
- **If the user logged-in with their email** , you can provide a button on the dashboard and [ask them to connect their Google Account](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider#connecting-a-social-account-to-an-existing-user). After that, you can access their Google Access Token by calling [Cotter's API](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider/getting-access-tokens-from-social-login-providers).

> When your user logged-in using Cotter, you'll get a **Cotter Access Token**. We'll use this access token to **protect our API Endpoints** that we're going to make in Cloudflare Workers.

**1) Adding Sign in with Google to your Login Form**

1. [Follow these instructions to set up Google OAuth 2.0 Credentials and connect it to Cotter](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider/google-instructions). Make sure you added `https://www.googleapis.com/auth/calendar` for the scope.
2. Enable Google for your form: Go to Branding > Magic Link Form > click the checkmark to enable [Google Sign In](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider#setting-up-social-login-provider)
3. Add Cotter's Login Form to your website

Using Cotter's React SDK, you can easily use React context provider to keep track of the authentication state (i.e. is the user logged-in, etc).

```bash
yarn add cotter-react
```
```javascript
import React from "react";
import { Router } from "@reach/router";
import LoginPage from "../login";
import { CotterProvider, LoginForm } from "cotter-react"; // 👈 Import Cotter Provider

function App() {
  return (
    // 👇 1) Wrap CotterProvider around your ROOT COMPONENT
    // Copy paste your Cotter API Key ID below.
    <CotterProvider apiKeyID="<YOUR API KEY ID>">
      <Router>
        <LoginPage path="/" />
      </Router>
    </CotterProvider>
  );
}

function LoginPage() {
  return (
      <div className="LoginPage__form-container">
      {/* 👇 2) Show the login form */}
      <LoginForm
          onSuccess={(response) => console.log(response)}
          onError={(err) => console.log(err)}
      />
      </div>
  );
}

export default App;
```

**2) Checking if the user is logged-in in your dashboard**

Using `CotterContext` you can check if the user is logged-in and get their Cotter Access Token.

```javascript
import { CotterContext, withAuthenticationRequired } from "cotter-react"; // 👈 Import the user context
import React, { useContext, useEffect, useState } from "react";
import "./styles.css";

function DashboardPage() {
  const { user, getAccessToken, isLoggedIn } = useContext(CotterContext); // Get the logged-in user information
  const [accessToken, setaccessToken] = useState(null);

  useEffect(() => {
    if (isLoggedIn) readAccessToken();
  }, [isLoggedIn]);
    
  // Get the Cotter access token to be used for our API call
  // (for now, we'll just display it in the dashboard)
  const readAccessToken = async () => {
    const token = await getAccessToken();
    setaccessToken(token?.token);
  };
  return (
      <div className="container">
      	User ID: {user?.ID} <br />
      	User email: {user?.identifier} <br />
        Cotter Access Token: {accessToken}
      </div>
  );
}

// Protect this page using the `withAuthenticationRequired` HOC
// If user is not logged-in, they'll be redirected to the `loginPagePath`
export default withAuthenticationRequired(DashboardPage, {
  loginPagePath: "/",
});
```

- Wrap your component around `withAuthenticationRequired` to automatically redirect your user to login if the user is not logged-in
- Use `isLoggedIn` to check if the user is logged-in, and `user` to get the logged-in user information.
- Use `getAccessToken` to get the Cotter Access Token that we'll use to call our API endpoints.

**3) Checking if the user has connected their Google Account**

We'll make an endpoint for this on our Cloudflare Worker which will call [Cotter's API](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider/getting-access-tokens-from-social-login-providers) to see if the user has connected their Google Account.

**4) Show a button to connect Google Account from the Dashboard**

![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/image-2.png)

If the user has not connected their Google Account (they didn't log in using Google), show a button to **connect Google Account.** Call this function with your button to connect their Google Account:

```javascript
import { CotterContext } from "cotter-react"; // 👈 Import the user context

function DashboardPage() {
  ...
  const { getCotter } = useContext(CotterContext);

  // If the user hasn't connected their Google Account,
  // show a button to call this function to connect
  const connectToGoogle = async () => {
    var cotter = getCotter();
    cotter.connectSocialLogin("GOOGLE", accessToken);
  };
    
  return (
    <div className="DashboardPage__container">
     ...
      <button onClick={connectToGoogle}>Connect Google Account</button>
    </div>
  );
}
```

* * *

# Cloudflare Worker Endpoints

![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/image-3.png)

## Making API endpoints at Cloudflare Workers to call Google's API

Once you got the login flow working, you can start making the endpoints at Cloudflare Workers that would call Google's API. Specifically, you'll need these endpoints:

1. An API to check if the user has connected their Google Account
2. An API to modify their Google Calendar

### Create a Cloudflare Account and Setup Workers

1. Go to Cloudflare and sign up with your email and password. **You don't need to add a domain.** When asked to add a domain, **if you don't have a domain, you can skip this by clicking on the Cloudflare logo.**
2. Click **Workers** on the right side of your dashboard, and add a subdomain that you want for your backend API endpoint. Choose the **Free Plan** and verify your email.

### Create a Test Worker to see how this works

1. Press **Create a Worker.** You can see that you have a handler script on the left side, and a playground to test your API endpoint. Click **Send** and you should see `hello world` as the response.
2. That's it, you've just created an endpoint! To save this endpoint, press **Save and Deploy**.

### Creating Endpoints

Notice that you can only change the sub-subdomain, not the path.

![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/10/image-15.png)

To be able to handle different paths, you'll need to **[use their CLI and use a router](https://developers.cloudflare.com/workers/starters)**. That's too advanced for this tutorial, so **we'll just have our endpoints on different subdomains**.

# Endpoints

## Endpoint #1: `checkconnection`

### Check if the user has Google Connected.

Create a worker, and change the name to `checkconnection` . We'll define our endpoint as the following:

```bash
$ curl --request GET \
    --header 'Authorization: Bearer <COTTER_ACCESS_TOKEN>' \
    --url 'https://checkconnection.YOUR_SUBDOMAIN.workers.dev?userid=<COTTER_USER_ID>'
```
```javascript
// If Google account is connected:
{"connected": true}

// If not:
{"connected": false}
```

### Here are the things that we'll need to do:

- Check if the Cotter access token is valid
- Call [Cotter's API to check if this user has a Google Access Token](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider#connecting-a-social-account-to-an-existing-user)

### Code & Env Variables

Copy the code from [our Github repo](https://github.com/cotter-code/calendar-booker/blob/main/cloudflare/checkconnection.js).

### Add the Cotter Api Keys as environment variables

Go to the Settings tab, and press Add Variable. Add both the `API_KEY_ID` and `API_SECRET_KEY` from Cotter, then press Save.  
 ![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/Screen-Shot-2020-11-02-at-3.40.14-AM.png)


## Endpoint #2: `createevent`

### Create a Google Calendar Event

Before we start, you'll need to Enable [Google Calendar API](https://console.developers.google.com/apis/api/calendar-json.googleapis.com) to the project that you used to create Google OAuth 2.0 Credentials.

Create another worker, and change the name to `createevent` . We'll define our endpoint as the following:

```bash
$ curl --request POST \
  --header "Content-Type: application/json" \
  --data '{"start_time":"2020-11-02T10:00:00-08:00","end_time":"2020-11-02T10:15:00-08:00","attendee_email":"attendee@gmail.com","meeting_title":"John Doe <> Jane Doe"}' \
  --url 'https://createevent.YOUR_SUBDOMAIN.workers.dev?userid=<COTTER_USER_ID>'
```

- `start_time` & `end_time` should be in formatted according to [RFC3339](https://tools.ietf.org/html/rfc3339)
- `attendee_email` is the email of the attendee (just 1 email)
- `meeting_title` is the title of the meeting

```javascript
{
    "success": true,
    "event": { ... Google's Event Obj }
}
```
<figcaption>Success Response</figcaption>

```javascript
{
    "success": false,
    "error": "Error message"
}
```
<figcaption>Error Response</figcaption>

**This URL doesn't require an authorization header** because we want anyone to be able to book an appointment without having to log in to your platform first.

### Here are the things that we'll need to do:

- Call [Cotter's API to get the user's Google Access Token](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider#connecting-a-social-account-to-an-existing-user)
- Use Google API [Event insert endpoint](https://developers.google.com/calendar/v3/reference/events/insert) using the Google Access Token

### Code & Env Variables

Copy the code from [our Github repo](https://github.com/cotter-code/calendar-booker/blob/main/cloudflare/createevent.js).

**Add the Cotter Api Keys and Google Credentials as environment variables**

- Again, we need to add the `API_KEY_ID` and `API_SECRET_KEY` environment variables from Cotter API Keys.
- We also need to add `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` environment variable from Google OAuth Credentials.

![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/Screen-Shot-2020-11-02-at-5.36.21-PM.png)

## Endpoint #3: `disconnect`

### Disconnect the user's Google Account

Create another worker, and change the name to `disconnect` . We'll define our endpoint as the following:

```bash
$ curl --request DELETE \
    --header 'Authorization: Bearer <COTTER_ACCESS_TOKEN>' \
    --url 'https://disconnect.YOUR_SUBDOMAIN.workers.dev?userid=<COTTER_USER_ID>'
```
```javascript
// If disconnected successfully
{"success": true}
```

### Here are the things that we'll need to do:

- Check if the Cotter access token is valid
- Call [Cotter's API to delete a user's Google Access Token](https://docs.cotter.app/sdk-reference/web/sign-in-with-social-login-provider/getting-access-tokens-from-social-login-providers#delete-an-access-token-from-a-specific-provider-for-a-user)

### Code & Env Variables

Copy the code from [our Github repo](https://github.com/cotter-code/calendar-booker/blob/main/cloudflare/disconnect.js).

**Add the Cotter Api Keys as environment variables**

- Again, we need to add the `API_KEY_ID` and `API_SECRET_KEY` environment variables from Cotter API Keys.

# That's it!

![Cotter + Cloudflare Workers + Google Calendar API: Build a Serverless Calendar Booking App](https://blog.cotter.app/content/images/2020/11/calendar.gif)<figcaption>Build a Calendar Booking App with Cotter, Cloudflare Workers, and Google API</figcaption>

You should now have your backend API set up and Google Sign In set up, all you need to do is connect them in your frontend. If you need some references on how to do that, check out our Github repo:

- [Frontend using React](https://github.com/cotter-code/calendar-booker)
- [Cloudflare worker endpoints](https://github.com/cotter-code/calendar-booker/tree/main/cloudflare)

### 👉 Try the live demo, it's fully functional

[Calendar Booking App by Cotter](https://cottercalendar.herokuapp.com/)

* * *

### Questions & Feedback

Come and talk to the founders of Cotter and other developers who are using Cotter on [Cotter's Slack Channel](https://join.slack.com/t/askcotter/shared_invite/zt-dxzf311g-5Mp3~odZNB2DwYaxIJ1dJA).

### Ready to use Cotter?

If you enjoyed this tutorial and want to integrate Cotter into your website or app, you can [create a free account](https://dev.cotter.app/) and [check out our documentation](https://docs.cotter.app/).

If you need help, ping us on our [Slack channel](https://join.slack.com/t/askcotter/shared_invite/zt-dxzf311g-5Mp3~odZNB2DwYaxIJ1dJA) or email us at team@cotter.app.