How to use Supabase in Next.js?

How to use Supabase in Next.js?

Published 8th, November, 2022

5 min read

Next.js is very recent, and yet has come up with so many interesting and exciting features to make your lives easier as developers! Supabase is the new kid on the block, an alternative to Firebase which is worth considering, because it provides almost all the features that you will find in Firebase, and have been developed with enterprise-grade open source technologies.

For starters, Firebase provides a range of diverse services and APIs that are ready-to-use solutions for applications to run. This includes general web hosting, authentication APIs, database and common cloud-based services for web applications to run. From a ‘developer stack’ point-of-view, Firebase strongly supports JavaScript and all its modern progeny, including Node.js and all its dependencies.

While Firebase still rules the roost and its significance has not waned yet, some developers came up with an idea to start an alternative that offers as much but less on costs. What makes Supabase really ‘super’ is that it has been built with development tools that are generally available that need no special subscriptions. These include PostgreSQL database, REST and GraphQL APIs for authentication and other purposes and file storage, to name a few.

Now that being said, let’s find out how can you combine Supabase with Next.js to create a robust application.

The basics

As an example, we are going to build a user account maintenance application where the user can login and manipulate/edit details about his account. And for this, we are going to need some basic tools such as database, API, storage, security setup and user authentication. All of these components have been provided by Supabase.

Creating project and database schema

Visit app.supabase.com and click on ‘New Project’, enter all its details and wait for your database to launch. And now, go to the SQL Editor page, where you can write your SQL script as per your requirements. If you are going to follow something ‘cookie-cutter’, you can just copy-paste a sample SQL script and build the database schema.

Insert data with API

After building the basic database, we need the auto-generated API to insert some dummy data, and for that we are going to get the ‘anon’ key from the API settings. On your dashboard, go to the Settings page, go to the API option on the page’s sidebar, where you will find the URL, service_role keys and ‘anon’ key.

Start the app

The create-next-app CLI command, followed by your app’s name, creates your app. Let’s call our app ‘super-next-base’


npx create-next-app  super-next-base --use-npm
cd super-next-base

This would require us to install only and only this basic dependency

npm install @supabase/supabase-js

And since we are creating a new environment for our application that will contains all the files and packages that we are going to need, we will get our API URL and the ‘anon key’ that we generated in the last snippet.

NEXT_PUBLIC_SUPABASE_URL = <your Supabase URL>
NEXT_PUBLIC_SUPABASE_ANON_KEY = <your anon key>

At this stage, we have got our API credentials and we are good to go to create our Supabase client. However, even though the associated variables will be seen on browser, Row Level Security ensures that the database is not tampered with.

In the SupabaseClientFile.js

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

const supabase_url = process.env.NEXT_PUBLIC_SUPABASE_URL;

const supabase_anonkey = process.env.NEXT_PUBLICSUPABASE_ANON_KEY;

export const supabaseObject = createClient(supabase_url, supabase_anonkey);

You can also make these edits to your globals.css file to implement the design aesthetics.

Building the Login logic

Inside the components/Authentications.js file

// TODO this code block seems wrong cross check it once again

import {
    supabase
} from‘ < enter > /<path>/supabase_client’

// besides, you will also need to import useState from React

export default function Auth() {

    const {
        found_error
    } = await supabase.auth.signInWithOtp({
        <
        your_email >
    })
    if (found_error) throw error {
        alert('You’ve been sent login link on email!')
    } catch (found_error) {
        alert(found_error.error_description || found_error.message)
    } finally {

        // here, set the <setLoading> function to ‘false’
    }
}

As a result of the above, now you can return whole HTML, which renders the HTML page itself. And we mean, the whole HTML code. Have a look.

<div>
	<input
		className="email_input"
		type="email"
		placeholder="Enter your email"
		value={email}
		onChange={(val) => setEmail(val.target.value)} />
</div>
<div>
	<button
		onClick={(val) => {
		val.preventDefault()
		implementLogin(email)
		}}
		className="button zone"
		disabled={loading}
	>
		<span>{loading ? 'In process' : 'I need the Link'}</span>
	</button>
</div>

Account page building

Since we have created the logic behind creating the client and handling login, we can now move to building the client’s account page.

Inside the components/Account.js, first we will import useState and useEffect from ‘react’ to enable saving the user’s current state on his account.


import { supabase } from '../<your>/<path>/SupabaseClientFile’

First, you need to define an Account function and add the ‘export’ keyword before it since it will be needed elsewhere. With a ‘session’ object passed as its argument. Then club together main features of the user’s account in an array and set them either ‘true’ or ‘null’ as arguments of the ‘useState’ function, depending whether you would need to preserve the variable values in between function calls. For example:

const[loading, setLoading] = useState(true)

Then, define a function that gets the user profile with the getProfile function within the useEffect() Hook.

useEffect(() => {
getProfile()
}, [currentSession])

### 3. Get the current user with this

```jsx

async function getCurrentUser() {
    const {
        data: {
            currentSession
        },
        error,
    } = await supabase.auth.getSession()

    if (error) {
        <
        code
        for throwing error >
    }

    if (!session?.user) {
        throw new Error('User is not logged in currently')
    }

    return session.user
}

Getting the profile of a current user is important in your application’s features. Therefore, you begin with an async function getProfile() (or any other name that you find suitable), keep the setLoading value as true and re-define the getCurrentUser() with an await put before its name.

Then, get the values of data, error and the current status of the user conditionally. For example, the program throws an error if data is not fetched and the status of the request is 406. On the other hand, if data is legitimate, set the entered values of user name, website and profile image.

Updating profile is the final milestone is this exercise. When updating their profile, users will have 3 main points of identification identified by the application; the user name, website and the URL for their Avatar. After taking these 3 variables as parameter inputs.

First, we’ll call the function for getting the current user and then create an object that contains the most common identifiers for a user’s account, such as updates, id, website, URL for their Avatar and a Date() object when the profile was updated.

And then, don’t forget to handle your errors.


let {
    checkError
} = await supabase.from('allProfiles').upsert(userUpdates)

if (checkError) {
    throw checkError
 }
} catch (checkError) {
    alert(error.message)
} finally {
    setLoading(false)
}
}

Next, call the return function and within it write the HTML for the profile update process.

The Supabase Finale

Once you are done taking care of these factors, now you need to edit your index.js file. First make these imports

useState and useEffect from react, supabase from the supaBaseClient in your utils directory, Auth and Account from your Auth and Account files in the components directory.

Export the default Home() function with the isLoading and setIsLoading with userState being True and session and setSession with state as null.

Now define and call a function that updates the react state, only when the components are active.


async function getYourSession() {
const {
data: { yourSession },
} = await supabase.auth.getSession()

if (compMounted) {
if (yourSession) {
setSession(yourSession)
}

setIsLoading(false)
}
}

getYourSession()

That’s it dear developers. We hope you found it interesting enough, even though it might look daunting!

References:

  1. supabase
  2. npmjs