Table of Contents
- Introduction
- Prerequisites
- What is Supabase and Setting Up the Supabase Project
- Integrating Supabase with ReactJS
- Exploring the Email Rate Limit Issue
- Implementing the Solution
- Conclusion
Introduction
Imagine this: you're building a web application with ReactJS on the frontend and Supabase as your preferred backend solution. You're making progress but suddenly realize you can only send 3 emails per hour on user registration. That sucks, right? Yeah, it does.
In this article, we will dive into how to integrate a React application with Supabase authentication, we will then look into how Supabase's built-in email functionality can become a bottleneck, as it limits the number of emails that can be sent within a given timeframe which can in turn hinder the scalability of your application.
All right, enough talk. Let's dive right in
Prerequisites
This article assumes that you know the basics of using ReactJS. It's also helpful if you're already familiar with integrating and using Supabase, though it's not mandatory. You can follow along even if you're not an expert. If you're here for just the solution, you're in the right place.
What is Supabase and Setting up the Supabase Project
Like stated on the image above, Supabase is an open source Firebase alternative that offers services like starting or having your own Postgres Database, Authentication, Storage, Realtime subscriptions and so much more. It's designed to help developers build and scale applications quickly and efficiently.
Let's set up a Supabase project. Head over to supabase website and create an account.
You will then be redirected to your dashboard to help create a project.
Here's how the dashboard will look like.
NB: You won't have any projects in it if you're just creating an account
Click on the New project
button and then you'll be asked to fill the following below:
Proceed to click on the Create new project
button. This creates the supabase project.
We are then redirected to our created project on our dashboard and it will look like this:
Congratualations, we've successfully set up our project on the supabase platform
Integrating Supabase with React JS
I would have loved to show you the full authentication system that includes features like login, logout, and protected routes. We will keep it simple and just focus on overcoming Supabase's email rate limits during registration.
Create a react project using vite using any of the commands below:
npm create vite@latest my-app -- --template react # javascript
npm create vite@latest my-app -- --template react-ts # typescript
After that, you have to install the supabase client library into your project. You can install it using the command below:
cd my-app && npm install @supabase/supabase-js
The command above enters the my-app
directory/folder and installs the supabase client library in the project
After this, we would need to create an instance of the supabase client:
Make a folder in your src
folder and call it supabase
then create a file named supabaseClient.ts
and populate it with the code below
NB: use .js
if you created a React Javascript project
import { createClient } from "@supabase/supabase-js";
// Create a single supabase client for interacting with Supabase API (authentication, database, storage etc)
export const supabase = createClient(
import.meta.env.VITE_REACT_APP_SUPABASE_URL,
import.meta.env.VITE_REACT_APP_SUPABASE_ANON_KEY
);
Let's get started building the User Interface(UI) for the Register page
import { useState } from "react";
import "./Register.css";
const Register = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [loadingStatus, setLoadingStatus] = useState(false);
const handleRegister = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
};
return (
<div className="registerPage">
<h2>Register</h2>
<form onSubmit={handleRegister}>
<div>
<label htmlFor="email">Email:</label>
<input
type="email"
required
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<label htmlFor="password">Password:</label>
<input
type="password"
required
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div>
<label htmlFor="confirmPassword">Confirm Password:</label>
<input
type="password"
required
id="confirmPassword"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
/>
</div>
<button type="submit">
{loadingStatus ? "Loading..." : "Register"}
</button>
</form>
</div>
);
};
export default Register;
This is what we have from the code above:
Now let's connect our Register page to our Supabase project.
We start by getting our SUPABASE_URL
and SUPABASE_ANON_KEY
keys from our created supabase project, which in our case is our supabase-article
So to get these keys, navigate to your Project Settings
then click on the API
link.
Here is a pictorial view of where the keys are:
Create a .env
file in your react root-directory, which in our case is the my-app
project. Now copy the keys and put them in a .env
file created
VITE_REACT_APP_SUPABASE_URL=<supabase_url>
VITE_REACT_APP_SUPABASE_ANON_KEY=<supabase_anon_key>
Replace supabase_url
and supabase_anon_key
with the API keys.
NB: Make sure the VITE_REACT_APP_SUPABASE_URL
AND VITE_REACT_APP_SUPABASE_ANON_KEY
variables are the same as what you used in the supabaseClient.ts
file above
Now let us proceed by doing some validations on the handleSubmit
function and connect registration page to supabase
Here's the updated code of the handleRegister
function:
const handleRegister = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault(); // prevents page from reloading on submit of form
setLoadingStatus(true)
// Do your validations here
if(password !== confirmPassword){
alert("Passwords do not match");
setLoadingStatus(false)
return;
}
// supabase registration
try {
const { data, error } = await supabase.auth.signUp({
email: email.trim(), // trim() removes white spaces from the text entered
password: password,
options:{
data: {
// add additional data here
}
}
})
if (error){
throw error
}
// check for user email uniqueness
if (data?.user?.identities?.length === 0) {
alert("Email already registered. Please try a different email.");
setLoadingStatus(false);
return;
}
console.log("User data:",data);
alert("Sign up successful! Check your email for the verification link")
} catch (error) {
console.log("Error signing up:", error)
// @ts-expect-error("allow")
alert(error?.message);
setLoadingStatus(false);
} finally {
setLoadingStatus(false);
}
};
The above code does the following:
-
e.preventDefault()
prevents the page from reloading when the form is submitted - We are checking if the
password
andconfirmPassword
state match. If they do not match, we stop the function from going further using thereturn
keyword. - We then use the created
supabase
instance created by accessing thesupabase.auth.signUp()
method and we pass in the required data. - We then check if the email being used to register has not been used. We know that emails are unique as no two users can have the same email.
If all things go as planned, we would have a registered user in our Supabase users database.
Let's test it out:
Below is the email we got from supabase asking us to verify our email address:
Now, once this is all completed, we can then go to Authentication
section of your supabase-article
project, this is where you'll see a list of registered users.
Now let us try to register another user:
This is bad for our application's scalability as we need users to be able to register on our apps for them to be able to use them.
We will look into the error and explore why it exists in the next section.
Exploring the Email Rate Limit Issue
We've seen from the previous section the email rate limit issue firsthand. Despite registering just one user (this can vary, but supabase only sends 3 emails an hour), Supabases's built-in email service quickly hits its limit, throwing errors that prevent further registrations.
Supabase's default email service is designed for TEST MODE use only, as highlighted in their documentation here
Here is a screenshot of what it says:
Now that we've seen this, let's implement the solution
Implementing the Solution
Head over to your project dashboard, in our case it's our supabase-article
then navigate to the Project Settings > Authentication
.
Scroll down to the SMTP Settings
section. You would see this picture
The Sender email
should be your email or your business email, while your Sender name
should be your name, business or product name.
Set the Host
to smtp.gmail.com
, and you can set the Port Number
to 465
or 587
Now the Username
should be your email address. The main thing we need is the password. This is gotten from your Gmail security settings
Open your Gmail and Navigate to Account
Click on the Security
option below:
To get your smtp password
, 2-Step Verification is required.
Click on the 2-Step Verification
below
Put on the 2-Step Verification
, then scroll down to the App passwords
section, you would be prompted with a new screen asking you to enter your App name
, you can use supabase-article
On clicking the Create Project
button, you will see the password as shown below. Copy it and save it somewhere as it is shown once. Remove the spaces and use the password in the smtp password
field.
Now that we have all that we need, you can click on the save
button
After we have done this, let us now go and adjust our Email rates
At the top of the SMTP Settings
section, you would see the text "Email rates can be adjusted here" as seen in the picture below"
Click on the here
link then you'll be redirected to this page below:
You can then change the Rate limit for sending emails
to any number depending on how well your application will be used.
Scroll to the bottom and click on the save
button.
Now let us try registering another user on our application
Now going to check our email, we see the images below:
Hooray 🎉🎉, we've successfully set up and use Gmails Smtp to help us bypass supabase's rate limits.
Conclusion
In this article, we found a workaround around supabase's rate limit. We used gmails smtp to help us bypass the rate limits. Thank you for reading up this point. I ask that you drop a like and share this article with your peers who will benefit from this.
You can check the codebase here
What are your thoughts on Bypassing Supabase's Email Rate Limit? Have you encountered something like this and how did you resolve it? Feel free to share your thoughts in the comments section below.
P.S. I'm currently looking for frontend developer opportunities. If you have any leads or are hiring, feel free to check out my resume or connect with me on LinkedIn. I'd love to hear from you!
Top comments (0)