Authenticating Next.js with Supabase auth magic links


How to authenticate in Next.js using Supabase magic links authentication

8 Dec, 2021 · 5 min read

Now that we have a basic understanding of Supabase and how we can interact with it, let’s see how we can use their auth system!

We’ll use their magic link login in this article, which I’ve been dying to try out.

We’ll be working on our existing Supabase example. I urge you to read through this article on setting up the basics environment for Supabase.

The result for today will look like this:

Adding Tailwind CSS to Next.js

We quickly add Tailwind CSS at this point, to make it look a bit fancier.

You can find the full detailed article on Tailwind for Next.js here.

But the summary is as follows:

Install all the dependencies

npm install -D tailwindcss@latest postcss@latest autoprefixer@latest

Init tailwind config

npx tailwindcss init -p

Add purge to tailwind.config.js file.

purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],

Edit styles/globals.css to look like this:

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

Checking Supabase auth state in Next.js

The cool part about all this is that we don’t need to set up anything new for a basic magic login.

It’s already supported out of the box.

We can open up our pages/index.js file and import the necessary dependencies.

import { useEffect, useState } from 'react';
import { supabase } from '../lib/initSupabase';

Then we can modify our component to have the following logic.

export default function Home() {
  const [session, setSession] = useState(null);

  useEffect(() => {

    supabase.auth.onAuthStateChange((_event, session) => {
  }, []);

  return <main>{!session ? 'Show login' : 'show profile'}</main>;

What we do here is define a new state, which holds the session object. By default, this is a null state.

However, once the auth from Supabase changes, we set the session to be that.

The useEffect hook will run only on mount as we defined the [] at the end of it.

Then we return a conditional statement based on the fact: do we have a session or not?

If yes, we show a login text else a profile text. We’ll start making these unique components just now.

Creating the login component

As mentioned, the login will happen through a magic link, so we want to capture an email from the user.

Start by adding a Login.js file to your components directory.

This component should import the following dependencies:

import { useState } from 'react';
import { supabase } from '../lib/initSupabase';

Then we can define our component.

export default function Login() {
  const [email, setEmail] = useState('');

  const handleLogin = async (email) => {
    try {
      const { error } = await supabase.auth.signIn({ email });
      if (error) throw error;
      alert('Check your email for the login link!');
    } catch (error) {
      alert(error.error_description || error.message);

  return (
    <div className='container mx-auto grid place-content-center min-h-screen'>
      <p className='mb-4'>Sign in via magic link with your email below</p>
        className='mb-4 border-2 border-gray-500 rounded-xl p-4 w-full'
        placeholder='Your email'
        onChange={(e) => setEmail(}
        onClick={(e) => {
        className='w-full mt-4 p-2 pl-5 pr-5 bg-blue-500 text-gray-100 text-lg rounded-lg focus:border-4 border-blue-300'
        <span>Send magic link</span>

We define a new state to capture the user’s email. And display a form where the user can fill out their email.

Once they click the button, it invokes the handleLogin function.

In return, they request the Supabase auth sign-in method and pass the email they provided.

We show a simple alert, and the user should now receive an email in their mailbox.

When they click this email, they will be logged in and shown the profile text!

Making the profile component

The profile component will be a bit easier. As for now, it will only show the user’s email address that we retrieve from the session.

Create a Profile.js file in the components directory.

import { supabase } from '../lib/initSupabase';

export default function Profile({ session }) {
  return (
    <div className='container mx-auto grid place-content-center min-h-screen'>
      <p>Oh hi there {}</p>
        className='mt-4 p-2 pl-5 pr-5 bg-blue-500 text-gray-100 text-lg rounded-lg focus:border-4 border-blue-300'
        onClick={() => supabase.auth.signOut()}

We pass a session in and show the user’s email from the session. We also give them the option to sign out from here.

Rounding it up

Head back over to the index.js page and import the two new components like so:

import Login from '../components/Login';
import Profile from '../components/Profile';

Then modify the render function to show these two components dynamically.

return <main>{!session ? <Login /> : <Profile session={session} />}</main>;

Note: Did you note that we are passing the session to the profile component?

And that’s it. We now have a magic link login!

You can find the completed example code on GitHub.

Thank you for reading, and let’s connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Spread the knowledge with fellow developers on Twitter
Tweet this tip
Powered by Webmentions - Learn more

Read next 📖

Next portfolio - Filter by category

30 Nov, 2022 · 5 min read

Next portfolio - Filter by category

A glance at Turbopack

17 Nov, 2022 · 3 min read

A glance at Turbopack

Join 2099 devs and subscribe to my newsletter