Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI

by Ikeh Akinyemi

11 min read · Jun 3, 2021

In this tutorial, we’ll learn how to build a headless Trello clone, a backend-only content management system using TypeScript, set up FaunaDB using Fauna SDK, and finally deploy our application through the Vercel CLI.

Goal 

At the end of the tutorial, readers will comfortably be able to use Fauna SDK with FaunaDB together with headless CMS concepts to build their applications, understand the core concepts, and implement them in their projects. Within this tutorial, our focus will be on managing our headless CMS using FaunaDB, and TypeScript to build a similar and simplified version of Trello, a Trello clone.

Disclaimer: We won’t be covering the drag and drop feature found within the Trello application. This will help us focus more on setting up our Headless CMS, the database, and the CRUD functions.

Prerequisite

The following tools will be used within our tutorial and would be necessary to successfully follow along throughout the whole project:

  • Basic knowledge of TypeScript.
  • Have NodeJS runtime installed on your local machine.
  • Basic knowledge of React and React Hooks.
  • Have yarn or npm installed as a package manager.

Introduction

We’ll begin by defining some concepts and tools that would be used within the tutorial. This will give us basic knowledge or an introduction to some implementation that we will see during this tutorial.

Fauna SDK is an open-source JavaScript driver that provides the capacities and resources required to interact with Fauna. This makes communicating with Fauna Database and other Fauna services easier through the frontend. 

A content management system (CMS) is a computer software used to manage the creation and modification of digital content.

CMS typically has two major components:

  • a content management application (CMA), a front-end user interface that allows a user, even with limited expertise, to add, modify, and remove content from a website without the intervention of a webmaster
  • a content delivery application (CDA) that compiles the content and updates the website

Fauna is a unique indexed document system that supports relations, documents, and graphs for unmatched modeling flexibility. Its query interface features complex joins and custom business logic (ala stored procedures), as well as support for real-time streaming and GraphQL. 

Using headless CMS in production is beneficial for software developers as it gives them the freedom to choose their choice of Frontend tool or framework to work with within the project.

Fauna provides serverless, multi-region, transactional database instances that are accessible via a cloud API.

It's easy to adopt and highly productive to use.

It gives developers the data safety and reliability they need, without the operational pain typically inflicted while working with databases. We can easily query our database using Fauna SDK, a lightweight JavaScript Driver.

Pros and Cons of Using FaunaDB and Headless CMS

Headless CMS Pros

  • Deploying to any hosting platform works easier with headless CMS. The applications (blogs, websites, etc) built with headless CMS have great support to work on various displays such as mobile devices, web device, and AR/VR devices.
  • It gives developers the flexibility to choose any frontend framework to work with since the frontend and backend are separated from each other. This makes it possible for us to pick any choice of front-end technology that suits our needs. 

Fauna Pros

  • We can query data using GraphQL or Fauna Query Language (FQL).
  • Access data in multiple models including relational, document, graph, and temporal.
  • We can easily access and manage our database through the terminal through Fauna Console as well as Fauna Shell.
  • Great features like built-in authentication, transparent scalability, and multi-tenancy are all made available on Fauna services.
  • Fauna makes it quite easy to create and use a Fauna database instance from within the development environment of the hosting platforms like Netlify or Vercel using serverless functions.

Headless CMS Cons

  • There will be a need to set up infrastructure and manage the presentational component of our site, app, or other experience all by ourselves.
  • In headless CMS, the frontend development is handled with separate software and tools, this means that the developers have to be familiar with multiple codebases to be able to handle their general project. 
  • Implementation of headless CMS is known to be more costly than the traditional CMS. Headless CMS applications that embody analytics are not cost-effective.

Fauna Cons

  • Querying our database using SQL queries is not yet supported.
  • FaunaDB is not offered as an on-premises database.
  • Fauna Query Language, FQL, is schemaless.

Setting Up The Headless CMS With FaunaDB

Our first step is to create the database that would be used in our app in the Fauna dashboard. If you have not created an account on Fauna before now, create one here. Once done, we are going to be welcomed by the dashboard screen: 

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 1

We click on the NEW DATABASE button to create a database for our application. The next screen would be to provide a name for our database, which we’ll use as our content management system, then click the SAVE button. Within this tutorial, we named it Trello_clone.

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 2

The next thing we have to do is create a collection in our database. A COLLECTION is similar to SQL tables that contain our data that can be categorized into a group of similar items. To create a new collection, we start by click on the NEW COLLECTION button:

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 3

Next, we choose a name for the collection we created above. This is the name we’ll use to organize our content. We’ll name our collection, trello_board then click on the SAVE button. 

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 4

The next step in setting up our database for our project is to create a new index. Go to the Indexes tab on the sidabar to create an index. We’ll use this index in searching documents in our Fauna database, specifically by matching given inputs against an index’s terms field. Click on the NEW INDEX button to create an index. In this tutorial’s project, we’ll name our index all_tasks

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 5

Next, after creating our index, is to create our document.

This will contain the contents/data we’ll use for our headless CMS application.

The content we'll use to populate our frontend would be created here. This is the core concept of Headless CSM, taking the management of our data away from the frontend.

Click on the NEW DOCUMENT button to navigate to the screen where we’ll get started with the text editor to create our documents. 

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 6

We just created a single task document that holds a content key with a value of what the task entails. We will use this to populate our frontend that will be built in the next part of this tutorial.

You can extend the document to contain more key/value fields according to the contents you will need within your frontend application.

To keep the project concise and simple to follow through, we will create four more documents/tasks to use within our project.

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 7

Next, we move on to create our React app, the frontend.

Get Started With the React Application

We begin our frontend development by bootstrapping our frontend with npx create-react-app my-app – template typescript to create a React application adding TypeScript support to it.

After this process is over, we’ll proceed with installing all needed dependencies such as FaunaDB SDK, styled-components, and Vercel in our React application.

We can use any other UI framework to also build our frontend application.

npx create-react-app my-app --template typescript

# we install other dependencies once our project is done/created

yarn add faunadb @types/styled-components styled-components

# next we install vercel globally

yarn global add vercel

We will start building different components of our front-end application. We will create a Navbar component within the components folder inside the src folder, src/components/Navigation, to contain our application name, Trello clone.

import styled from "styled-components";

const Navbar = () => {
return (
  <Wrapper>
    <h1>Trello Clone</h1>
  </Wrapper>
);
};
const Wrapper = styled.div`
background-color: #02111b;
color: #fcfcfc;

& > h1 {
  margin: 0px;
}
padding: 1rem 2rem;
`;
export default Navbar;

After we imported the Navbar component within our App components, the above code coupled with the stylings written with the styled-components library, will turn out to look like the below UI: 

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 8

Next, we’ll create the body of the website that will contain the task data from our database. We’ll build another component, called Column, which will contain our tasks created on the backend database.

import styled from "styled-components";
const Column = () => {
return (
  <Wrapper>
    <h3>Web Development</h3>
    <ul>
      <Li key={1} id={`ID-number`}>
        <p></p>
        <div>
          <button type="button">Complete?</button>
        </div>
      </Li>
    </ul>
  </Wrapper>
);
};

const Li = styled.li`
border-radius: 0.3rem;
color: #fcfcfc;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #5b6c5d;
margin: 1rem 0.4rem;
& > p {
  margin-left: 1rem;
}
& > div {
  margin-right: 1rem;

  button {
    background-color: #fcfcfc;
    padding-top: 0.4rem;
    padding-bottom: 0.4rem;
    border: none;
    border-radius: 0.3rem;
    cursor: pointer;
  }

  button:hover {
    background-color: #eee;
  }
}
`;

const Wrapper = styled.div`
width: 45%;
border: 2px solid #ff6b6b;
border-bottom-right-radius: 0.4rem;
border-bottom-left-radius: 0.4rem;
& > h3 {
  background-color: #ff6b6b;
  margin: 0px;
  padding: 1rem 1.5rem;
}
`;
export default Column;

We created the column that we will populate later with tasks from our Headless CMS. The above code contains styles for JSX that we created.

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 9

Integrate Fauna SDK Into Our React App

Create a new file db.js at the directory path src/config/. Then import the faunadb driver and define a new client.

The secret passed as an argument to the faunadb.Client() method is going to hold the access key from .env file:

import faunadb from 'faunadb';
const client = new faunadb.Client({
  secret: process.env.REACT_APP_DB_KEY,
});
const q = faunadb.query;
export { client, q };

Next, we create a new directory called src/api/ and inside it, we’ll create a new file called index.js. We write our CRUD function here:

import { client, q } from "../config/database";

//Fetch All Items from Database;

const fetchAllTasks = client
.query(q.Paginate(q.Match(q.Ref("indexes/all_tasks"))))
.then((response: any) => {
  const taskRef = response.data;

  const fetchAllDataQuery = taskRef.map((ref: any) => {
    return q.Get(ref);
  });

  return client.query(fetchAllDataQuery).then((data) => data);
})
.catch((error) => error.message);

//Delete task from Database

const deleteTask = (taskId: number) =>
client
  .query(q.Delete(q.Ref(q.Collection("trello_board"), taskId)))
  .then((res) => res)
  .catch((error) => error.message);

export { fetchAllTasks, deleteTask };

The next step is to update our Column component, defining the useState and useEffect hooks that will help us query our CMS, and store the data for use on the frontend. You should also import the functions to query the CMS alongside. Our code should look like the code below:

import styled from "styled-components";
import { fetchAllTasks, deleteTask } from "../../api/index";
import { useEffect, useState } from "react";

const Column = () => {
const [tasks, setTasks] = useState<any[]>([]);

useEffect(() => {
  fetchAllTasks.then((res: any) => {
    setTasks(res);
  });
}, []);

const handleDeleteItem = (
  event: React.MouseEvent<HTMLElement>,
  id: number
) => {
  event.preventDefault();
  deleteTask(id).then((res) => res);
  const newTaskArr = tasks.filter((task) => task.ref.id !== id);
  setTasks(newTaskArr);
};

return (
  <Wrapper>
    <h3>Web Development</h3>
    <ul>
      {tasks &&
        tasks.map((task) => (
          <Li key={task.ref.id} id={`${task.ref.id}`}>
            <p>{task.data.task.content}</p>
            <div>
              <button
                type="button"
                onClick={(event: React.MouseEvent<HTMLElement>) =>
                  handleDeleteItem(event, task.ref.id)
                }
              >
                Complete?
              </button>
            </div>
          </Li>
        ))}
    </ul>
  </Wrapper>
);
};
...

With the complete code structure above, our Trello clone application should look like the below UI:

Build A Headless Trello Clone With Fauna SDK, TypeScript, and Vercel CLI 10

Within our src/api/ functions, we defined a deleteTask action to delete our items. We can still go to our CMS, that’s the database, and delete the items. 

Deploying To Vercel

Visit Vercel to register an account if not registered. The following steps will get our project hosted from your terminal:

vercel login# provide the right answers to the prompts
vercel

Below is a sample answer to the prompts:

vercel
? Set up and deploy "~/Projects/JavaScript/React JS/trello_clone"? [Y/n] y
? Which scope do you want to deploy to? ikehakinyemi
? Link to existing project? [y/N] n
? What's your project's name? (trello_clone)
  # click enter if you don't want to change the name of the project
? In which directory is your code located? ./
  # click enter if you running this deployment from root directory
? ? Want to override the settings? [y/N] n

This will deploy your project to vercel platform.

Conclusion

Congrats! You made it to the end. The combination of Fauna with Headless CMS concepts allows you to build a great web application that needs data to be stored and retrieved for use on the front-end. Here’s the GitHub link to the code sample we used within our tutorial.

Good luck!