Supabase Crash Course

Jeff P
8 min readFeb 12, 2024

Supabase is an open-source Firebase alternative that provides a suite of tools and services for building and scaling applications. It offers a variety of features typically required for modern web and mobile app development, including:

  1. Real-time Database: Supabase provides a real-time database similar to Firebase’s Realtime Database. Developers can store and sync data in real-time across connected clients.
  2. Authentication: Supabase offers authentication services, allowing developers to manage user authentication and authorization securely. It supports various authentication methods, including email/password, social login (such as Google, Facebook, GitHub), and third-party authentication providers.
  3. Storage: Supabase provides object storage for storing and serving files, such as images, videos, and documents, to users.
  4. GraphQL API: Supabase offers a GraphQL API layer on top of the underlying database, enabling developers to query and manipulate data using GraphQL queries. This allows for more flexible and efficient data fetching and manipulation.
  5. Serverless Functions: Developers can deploy serverless functions on Supabase, allowing them to run custom backend logic without managing servers. These functions can be triggered by various events, such as HTTP requests, database changes, or scheduled tasks.
  6. Real-time Pub/Sub: Supabase includes real-time pub/sub functionality, allowing developers to build real-time features such as live chat, notifications, and collaborative editing.
  7. Monitoring and Analytics: Supabase provides monitoring and analytics tools to track and analyze usage, performance, and errors in applications.

Supabase is built on top of open-source technologies, including PostgreSQL, which serves as the primary database engine. It aims to provide developers with a powerful, scalable, and cost-effective platform for building modern applications, while also offering the flexibility and control that comes with open-source software.

Setting up a table

Once you’ve setup an account at https://supabase.com/ you can begin setting up tables:

You create a new table by giving it a name and an optional description. You’ll see that you have two columns by default — id and created_at. You should probably keep those, and add more columns. So for example, we’ll create a column called “name” with a type of “text” and no default value.

Once you’ve added all the columns you want, hit save, and it will display your table:

Let’s add some information to our table, by populating one row of information.

Once saved, we’ll have our first row….

We’ll now add another table…

and another…

Relationships between tables

Let’s create one more table called “bookings”

However for this table, we’ll create a special “foreign key relation” for the cabinId column. Here we will connect the cabins table primary key (id) to this table…

We’ll add in another column for the guestId, which will allow us to create a foreign key relation to the “guests” table…

Let’s try populating a bookings table row…

What you’ll find is that when you get the the special columns we added (cabinId and guestId) there will be a clickable option to select which row in each of these tables we want to use….

if we click on these buttons, we’ll be able to select a row….

The important thing to understand here in terms of the table relationships is that each booking can only have one cabin assigned to it, and only one guest who has made the booking.

As time goes by, the cabins will get re-used and be booked again. Also, your guest may book again to re-visit and book a different cabin at a different date…. so the cabin can change, and the guest can change….. but you can still only ever assign one cabin and one guest to each booking. So for every “row” in your bookings table, you’ll have one instance of a guest row, and one instance of a cabin row.

This is why you create the guestId and cabinId in the bookings table….because that then means you can add foreign key relations to access all the rows in the guests table and all the rows in the cabins table.

RLS (Row Level Security) Security Policies

If we switch to the “API docs” tab in Supabase, we’ll now see the following:

If we go into the bookings option, we can actually the different ways we can connect to our table remotely…

in the top-right corner you’ll see when can connect via Javascript or via Bash….

If we switch to Bash, and then scroll down to the “Read All Rows” option, and then click where it says “hide” in the top-right corner, we’ll be able to switch to “anon (Public)” to reveal our API key and a full curl request to access our table…

If we were top then paste this entire curl request into a command prompt and hit enter, we should be able to retrieve the table dat for our bookings table…. let’s copy the entire thing into a command prompt…

Note: if using Windows command prompt, you’ll probably first of all need to copy the CURL into a text editor, and then replace the single quotes around the URL with double-quotes, and also replace the backslashes (\) with these symbols (^) before pasting the entire thing into command prompt.

If the response you get back it a set of empty square brackets, the connection worked!

It means there’s a connection to the bookings table, but we just now need to set our RLS (Row Level Security) correctly.

We need to do this in the Authentication tab under policies.

We’ll click “new policy” for our bookings table, and then click on “Get started quickly”

You’ll see multiple policy template options available, but for now we’ll just select the “Enable read access to everyone” option, and then click “Use this template”

We then click “review” and “save policy” and we’ll now see the policy has been applied…

Now if we try the curl request in our command prompt, we should now see our table data….

We’ll repeat the same process for all our tables so that we can at least retrieve our data from our React application for now…

Connecting React Application to database tables

We can connect via React using the NPM Supabase package:

npm i --save @supabase/supabase-js

Next we’ll create a supabase.js file, and add the following:

import { createClient } from "@supabase/supabase-js"; 

const supabaseUrl = "";
const supabaseKey = "";
const supabase = createClient(supabaseUrl, supabaseKey);

export default supabase;

We’ll then need to provide our URL and API key. These can be obtained from the “Project Settings” -> “API” page:

Retrieving cabin data

So now we could create a file called apiCabins.js and could paste in the suggested code from the API section of the Supabase page to read all rows…

And this code we’ll place inside an asynchronous function….

// apiCabins.js
import supabase from "./supabase";


// our named getCabins function
export async function getCabins() {
let { data: cabins, error } = await supabase.from("cabins").select("*");

if (error) {
console.error(error);
throw new Error("Cabin data could not be loaded");
}

return cabins;
}

So from the “cabins” table, we want to select ALL (*)

If we receive an error, we’ll deal with it with a simple if statement, but assuming we receive the data, we’ll then return it.

Now let’s attempt to use this data….

import { useEffect } from "react";
import Heading from "../ui/Heading";
import Row from "../ui/Row";
import { getCabins } from "../services/apiCabins";

function Cabins() {
useEffect(function () {
getCabins().then((cabins) => console.log(cabins));
}, []);

return (
<Row type="horizontal">
<Heading as="h1">All cabins</Heading>
<p>TEST</p>
</Row>
);
}

export default Cabins;

so we’ve imported our named function, then used it inside a useEffect to load it when the page loads, and then logged the data to the console:

Storage Buckets

Storage buckets in Supabase are great for uploading large files and images. So for example, we could create a storage bucket for avatars, and aanother for cabin-images

You can then simply drag and drop your images into the folder:

You can then click on an image to obtain its URL:

and with tthis URL we can show the imaage in our application:

import { useEffect } from "react";
import Heading from "../ui/Heading";
import Row from "../ui/Row";
import { getCabins } from "../services/apiCabins";

function Cabins() {
useEffect(function () {
getCabins().then((cabins) => console.log(cabins));
}, []);

return (
<Row type="horizontal">
<Heading as="h1">All cabins</Heading>
<p>TEST</p>
<img
src="https://nvlnrznxocinxmxqohvs.supabase.co/storage/v1/object/public/cabin-images/cabin-001.jpg"
alt="Cabin001"
/>
</Row>
);
}

export default Cabins;

Which should now display the image on our page…

We could of course now copy this URL directly into our table, so that the image data contains the URL….

Programmatically upload images

TBC

--

--

Jeff P

I tend to write about anything I find interesting. There’s not much more to it than that really :-)