A Step-By-Step Guide to Creating a Twitter Clone With React and Supabase — Part 1

James Kim
Geek Culture
Published in
6 min readApr 5, 2021

--

Recently, I’ve discovered Supabase, an open-source Firebase alternative that sets up your back-end in 2 minutes, and no product had me as excited as this one recently. So I’ve decided to write guides to show people how awesome this product is! 📢

In this series, I’ll be creating a Twitter clone with React and Supabase. If you follow along, by the end of the series, you will have deployed a fully functioning app that lets users:

  1. tweet out what they are thinking,
  2. upload avatars and change their profile,
  3. be notified when there are new tweets, and;
  4. be notified when someone has liked their tweet.

While you are making this app, you’ll learn how to:

  • set up a complete authentication flow for your users: Sign-ups, sign-ins, confirming emails, and forget passwords.
  • set up scalable storage so that your users can upload files
  • set up Row Level Security in your database so that users’ private data are locked down.
  • set up client-side routing using react-router-dom
  • set up client-side validation for forms using react-hook-form
  • quickly make an app look good using Material UI

I’ll assume that you have a basic knowledge of React when I’m explaining my code. If you are already proficient with React, I’ll also provide a git hash in the later part, so you can skip the React part.

Hang on a minute, What is Supabase?

Supabase’s landing page

Supabase is a Google Firebase alternative, that lets you have a fully functioning back-end in minutes. I’ve enjoyed using Firebase to quickly get my side-projects going, but the following things always annoyed me:

  1. I have to use a NoSQL DB, rather than PostgresDB,
  2. it is not open-source, and
  3. Biggest of all, there is no easy way to migrate out of Firebase when you out-grow it (especially all the users)

Supabase solves these problems because they:

  1. use PostgresDB under the hood,
  2. use and contribute to open-source libraries, and
  3. you can easily migrate out of Supabase and start self-hosting if you wanted to.

They also have a pretty generous free tier. By the way, I’m not paid by Supabase to write this, I am just excited about this product. Now that we know what Supabase is, it’s time to start building! Let’s get set up first.

Setting up Supabase

Sign in to Supabase (sign up if you haven’t already!), then create a new project. You will be faced with the below modal.

  • Name — put in anything you want. I’ve named mine supabase-twitter-example.
  • Database password - make a strong password and save it in your password manager.
  • Region - any region you'd like, I've set it to Sydney.

After clicking “Next”, you will need to wait 2 minutes for the back-end to be set up by Supabase. ⌚️ While that’s happening, let’s go set up the front-end.

Setting up Front-end codebase with create-react-app

Let’s bootstrap a react app using create-react-app. Run the following in your CLI to create a project with typescript.

npx create-react-app --template typescript react-twitter-clone

Install material UI

We want our app to look nice, but also we don’t want to spend too much time tinkering with styles. So we will be using a UI Library called Material UI. Run the following in the app’s directory to install the framework and the icons.

yarn add @material-ui/core @material-ui/icons

Let’s head back to Supabase, to see if our back-end has been set up.

Back to Supabase

If it’s all done, you’ll be greeted by this screen.

So many possibilities!

While you are on this screen, I’ll give you a quick rundown of where things are.

  1. Table Editor — This is where you can create, edit and view tables in your PostgresDB
  2. Authentication — This is where you can see your users and their status, and edit templates for emails that get sent as a result of user auth flow (like confirm sign-up emails!)
  3. Storage — This is where you can add, edit and view files in your S3 storage
  4. SQL — This is where you can run ad-hoc SQL queries and create stored procedures.
  5. API — This is where you can see a live-generated API doc for your backend
  6. Database — This is where you can do some database admin like roles, backups, and replication.
  7. Settings — Other settings live here. This is where you’ll be getting your API keys to use, later on in the series.

Now, let’s create some tables! Remember that we wanted users to be able to upload avatars and change their profiles? To do that, we need a profiles table, which we’ll make now.

Go to the SQL menu. When you are greeted by a welcome screen, select the option on the bottom screen. This is a handy template that Supabase provides, to quickly get us started.

When you do, you will be greeted with some SQL (which has not been run yet). Let’s go through them, to find out what is going to happen. At the top, we have:

We are creating a table called profiles with the following fields:

  • id, usesid from auth.users. This table has been automatically set up by Supabase and contains users after they've signed up. It must not be null because to have a profile, you need a user.
  • updated_at, a last updated at timestamp
  • username, avatar_url and website are self-explanatory.

Let’s have a look at the next snippet — which is the really exciting part.

The above snippet creates Row Level Security, which can lock down rows depending on the user. For example, you don’t want users to be able to update profiles that aren’t theirs!

To do this, when you get a request to update a profile, you want to check that the request is from the profile’s user (authentication), then if they are, let them do it (authorization).

Supabase can handle this for you, just with this little bit of snippet.

This is saying: only allow updates for the row, if auth.uid() matches the id. auth.uid() comes from the JWT token that will be sent with the requests if the user is logged in.

The official doc’s explanation of how this works, included below, is pretty good:

  1. A user signs up. Supabase creates a new user in the auth.users table.
  2. Supabase returns a new JWT, which contains the user’s UUID.
  3. Every request to your database also sends the JWT.
  4. Postgres inspects the JWT to determine the user making the request.
  5. The user’s UID can be used in Policies to restrict access to rows.

The next snippet adds real-time notification support, which we will skip for now.

The last bit of snippet is also exciting. Let’s have a look:

Supabase also comes with Storage built-in (that uses S3 under the hood), and we can set policies for accessing the storage by using SQL! How convenient is that?

Now that, we know what the SQL query is doing, smash the RUN button. In the Results tab, there should be a message saying Success. No rows returned .

When you return to the Table Editor view, you should see a table called profiles.

Woohoo 🎊, just with a couple of clicks we’ve made a table with:

  • Row Level Security, so that user’s data are secured
  • Real-time notification support, and;
  • we’ve made an object bucket with some security policies.

In the next series, we will be building some react front-end to use our newly made back-end! Follow me on Twitter (@James_HJ_Kim) so you don’t miss out on Part 2. See you then!

--

--

James Kim
Geek Culture

Backend Engineer working at Xero. Also passionate about UX, writing and illustration.