DEV Community

Cover image for Building a startup (build log 2#): Authenticating students with Supabase
Paul-Simon Emechebe
Paul-Simon Emechebe

Posted on

Building a startup (build log 2#): Authenticating students with Supabase

I've decided to start documenting my journey as the CTO of Grow. Here is the second build log (build log 2#) where I discuss in detail the development process of how I built the authentication layer for our dashboard.


What is Grow?

This is a tweet from our CEO at Grow describing what Grow is.

What Grow is


In this build log, I'll go through the authentication layer for the Grow dashboard. The Grow dashboard is where authenticated users (registered Grow students) have access to course materials, recorded lecture sessions, course agendas, student progress logs, etc. At the time of this publication, the Grow dashboard is still in the infant stages of its development.



In this build log, I'll be covering the following;

1. The tech stack

2. The login page UI

3. The authentication flow

4. The validation logic



The tech stack

The four main dependencies are React, Next.js, Tailwind, and Supabase.

  1. React.js: I'm using React to build the dashboard. React is an open-source Javascript UI library for building UI components. The concept of React is breaking down your app into independent components that can be completely isolated from the rest of the app when developing, this is possible due to Reacts rendering behavior. Learn more about React.js here
  2. Next.js: Next.js is a web framework built on top of React. Amongst a lot of the features it provides, the most notable one is SSG (server-side rendering). One of the best features Next.js provides is its file-based routing system.
  3. Tailwind: Tailwind is a CSS framework that gives you the ability to inline-style using pre-built utility classes. Learn more about Tailwind here
  4. Supabase: Supabase is a suite of open-source tools/software to help you build apps using Postgres. The Supabase database is what we used to store all the data for our registered students. They also offer authentication but I didn't see the need to do my user validation on Supabase, I just needed Supabase to give me all our users, then I'd handle the validation logic on the client. Why? I'll touch on that in the authentication flow section. Learn more about Supabase here



The login page UI


login UI


In this section, I go through the process of building the UI of the login page i.e styling, folder structure, and component structure.
At the time of this publication, the UI of the login page was not yet built with our custom UI components (e.g Form, FormInput, and FormLabel). So a lot is happening in this single file. No custom hooks, no reusable UI components, and no helper functions. All the logic was done in this single file. This is bad practice for it will catch up with you once you start scaling. Below will show you screenshots of the file.

DISCLAIMER: I am not encouraging this approach to building components. I am just citing an example of what not to do. I built it like this temporarily, just to get something running. Depending on the time you are reading this, the UI must have been written with good scalable practices.


  • Too many Usestate. This is meant to be avoided by dedicating specific state logic to custom hooks. Too many useStates


  • Redundant styling and HTML. This is meant to be avoided by building custom UI components that carry identical styling and possibly logic for the sole purpose of them being reusable. From the picture below. line 131 signifies the start and line 267 signifies the end. Do the math, that's a total of 136 lines of code for just a login page. That's too many lines of code.

redundant styling and html



Authentication flow

Here I go through the user journey of the login page.


authentication flow


These are the steps that the User undergoes to get authenticated as a student.

  • Step 1: The user does a manual registration in the venue of the Bootcamp and gets an OTP code.
  • Step 2: The user goes to the Grow Dashboard login page.
  • Step 3: The user logs in with the first name he/she used for the manual registration and the OTP code.



Validation logic

In this section, I discuss the logic I wrote to securely validate that the user logging in is indeed who he/she claims ( input ) to be.
First of all, we'll take an overview of what happens behind the scene. Below is a diagram of two parties, the client ( the app ) and the database/server ( Supabase ). Supabase provides a feature called Supabase Auth that deals with authenticating users. I didn't use Supabase Auth to authenticate my users, why?
Due to the fact we are a young startup, we are targeting our students locally. So there was no need of integrating an online payment gateway so we did our payments in person. The in-person payment also requires the student to fill out a form citing the student's credentials. Once the student has done this, the student is officially registered. After this manual registration, the student will be sent an OTP to his/her email to verify his/her account and access his/her dashboard.

The user data for authentication were

  1. Students registered full name: The full name the student used for manual registration.
  2. OTP code: The code is sent to the student's email after manual registration has been completed.

login UI
Now for the validation logic.


NOTE: In the next build log ( build log #3 ), I'm going to discuss the validation logic in detail (line by line). The explanation below is just skimming through the important stuff.


validation logic diagram

As you can see above, Supabase doesn't handle the validation logic, all it does is provide all the credentials of manually registered students.


So what's happening on the client side?


validation logic functions


I have

  • two functions handling the validation logic ( readSupabse, onAuthenticate )
  • one useEffect
  • two components (FullnameValidatoinIcon, OtpValidationIcon)


    Let's briefly describe what they do;


This function contains a Supabase API that does two things;


  • reads a list of all the students registered on the database with their various credentials bound to each student.
  • filters the list and spits out all the student's full name and OTP codes only after this API call is run, the filtered data is compared with the user's input. The comparison returns a boolean. so validation is done anytime the user triggers an onChange on the input field. More on this will be discussed in the next build log (build log 3#).


    The logic from the readSupabase function starts checking wether the user is valid or not once the user starts typing

below is the validating state
validating state


below is when the validation is false

validation is false


below is when the validation is true

validation is true


This runs once the user clicks the login button. This function does several things;

  • starts the loading state
  • checks whether the full name exists in the database
  • checks whether the OTP exists in the database
  • checks whether the full name and OTP are bound to the same student
  • starts a modal state
  • redirects to the dashboard


NOTE: in the next build log, I'll go through these line by line


FullnameValidationIcon, and OtpValidationIcon:
These two components handle the icons on the right of the input fields. They are responsible for displaying the;

  • error icon: signifying that the user's input does not match what is in the database
  • check icon: signifying that the user's input matches what's on the database.





As of the time of writing this, no refactoring was done whatsoever. It's the first iteration of the login page. I just wanted to get things running, in future build logs, I'll discuss how I refactored the login page. Thanks for reading, if you have any suggestions, criticism, or even ways to make these build logs add more value to you guys, feel free to let me know in the comment section below. Have a good day!

Top comments (0)