How i created a React Native app with Supabase
⛈️ @supabase invited me to take part in their Content Storm, so I'm writing an article about a mobile application I made largely with Supabase and its features.
Note: Screenshots of the application will be in French 🇫🇷
Summary:
- What needs does my application fulfill? a. User (employee) b. Admin (manager)
- How do I use Supabase?
- Authentication
- Database
- Storage
- Edge functions
- Deployment
- Choice of technologies
- Updates
1. What needs does my application fulfill
My application is a simple clocking-in application for the company I work in. The website they use is good but not tailored enough to their needs.
For simplicity, I used React Native Paper.
a. The employee should be able to clock in easily without too many actions. b. The manager should be able to view their employees' clock-ins, approve, or modify a clock-in if necessary.
2. How do I use Supabase?
Authentication
Supabase is used to manage user accounts with an email address and password. No need for providers such as Google or GitHub.
A simple line of code like this:
const { error } = await supabase.auth.signInWithPassword({ email, password });
For registration, the employee must be approved by a manager, so I use an Edge Function to send notifications to a certain approved person to alert them of a new registration.
const handleRegister = async(): Promise<void> => { setLoading(true); const { data: { session }, error } = await supabase.auth.signUp({ email, password, options: { data: { firstName, lastName } } }); await supabase.functions.invoke("get_approbator").then(async(response) => { await supabase.functions.invoke("push", { body: { record: { user_id: response.data.userId || "", title: "New registration", body: `${firstName} ${lastName} has signed up, click here to go to the approval page`, action: OPEN_APPROVAL } } }) .then(() => console.log("Notification sent!")) .catch((error) => console.error("Register push error:", error)); }).catch((error) => console.error("Register get_approbator error:", error)); if (error) { setError(error.message); setLoading(false); } else { setLoading(true); const { error } = await supabase.from("users").upsert({ userId: session?.user?.id || "", firstName, lastName, email, fcm_token: fcmToken, role: "EMPLOYEE", notify_approvals: false, avatar: getAvatar(firstName, lastName) }); if (error) { setError(error.message); setLoading(false); console.log("Error (handleRegister in RegisterScreen.tsx l39):", error.message); } setLoading(false); setError(""); } };
Once the user is logged into their account, they can now clock in.
Database
The PostgreSQL database has 3 tables: checks
, users
, and versions
.
checks
which stores users' clock-ins.
users
which stores the users, having a relationship with theusers
table from theauth
schema to link theuser_id
of the created account with Supabase Auth.- A link with Storage to retrieve the user's avatar.
versions
which will store, using Storage, the versions (with an.apk
file) of the application to tell users if they have an update available.
Storage
Edge functions
I used Edge Functions for various things:
- Updating data
- Sending notifications
- Retrieving data
For example, here's how I send notifications with Supabase and Google FCM:
- First, I set up some constants like initializing Supabase and adding some types.
- Then, I made the function that retrieves the user's FCM Token.
- Then a function with
Deno
to send the request to Google APIs and send a notification.
3.1. Choice of technologies
3.2. Updates
The absence of the application in the stores poses two problems: it's complicated for iOS users to update their applications. Currently, this is not a problem for our team as only one member has an iPhone, but they also have an Android device, which solves the problem. However, if someone else joins the team with an iPhone in the future, we won't be able to continue like this.
I don't have a Mac (or any other Apple device) to compile the application
and deploy it to the App Store.
For Android, we have the .apk
files, I tried just before deploying it to the Play Store but too many "settings" requested unnecessarily since it's an application for a team in a company so it's not an application meant to be downloaded by thousands of people (outside the company).
That's why I opted to make my own update system that will check with a Database Function
via Supabase the latest available version in the versions
table.
When the user clicks Download
, it will retrieve the APK file placed in Storage, download it, and execute it to open the Android update dialog.
Extract of some useful Kotlin code for this operation:
~~Extract of~~ the TSX file code of my dialog to display and update the application
Note: Here are some links to the code (GitHub Gists)
I've never made mobile applications before 😲
Thanks for taking the time to read this article!
You can find me on X @steellgold
You can find and test Supabase on X. This post uses Supabase Storage to store images.