Supabase Login With Next.js: A Quick Tutorial

by Faj Lennon 46 views

Hey guys! In this guide, we're diving into how to set up a Supabase login page using Next.js. Supabase is an awesome open-source Firebase alternative that makes it super easy to handle authentication, databases, and more. Next.js, on the other hand, gives us a fantastic React framework for building fast, scalable web apps. Marrying these two technologies can save you a ton of time and effort, so let's jump right in!

Setting Up Your Next.js Project

First things first, let’s get a Next.js project up and running. If you already have one, feel free to skip this part. Open your terminal and run the following command:

npx create-next-app supabase-login-app

This command uses create-next-app, which is the official Next.js CLI tool, to scaffold a new project named supabase-login-app. Once the project is created, navigate into the project directory:

cd supabase-login-app

Now, let's install the Supabase client library. This library will allow us to interact with our Supabase project from our Next.js application. Run the following command:

npm install @supabase/supabase-js

With our Next.js project set up and the Supabase client installed, we’re ready to move on to setting up our Supabase project. Trust me, it's easier than it sounds!

Creating a Supabase Project

Next, you'll need a Supabase project. Head over to Supabase and sign up for an account if you haven't already. Once you're logged in, create a new project. You'll be prompted to choose a name, a database password, and a region. Choose a name that reflects your project (e.g., "Next.js Login App"), set a strong password, and pick a region that's geographically close to your users for the best performance. After filling out all the necessary info, create the project.

Once your project is created, navigate to the "Settings" tab in the left sidebar, then click on "API". Here, you'll find your Supabase URL and anon key. These are essential for connecting your Next.js app to your Supabase project. Make sure to keep these keys secure and never expose them in your client-side code. Instead, we'll use environment variables to store them.

Back in your Next.js project, create a .env.local file in the root directory. Add the following lines to the file, replacing the placeholders with your actual Supabase URL and anon key:

NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key

Important: The NEXT_PUBLIC_ prefix is crucial. It tells Next.js to expose these environment variables to the client-side code. Without this prefix, the variables will only be available on the server-side.

Now that we have our Supabase project set up and our Next.js app configured with the necessary credentials, we can start building the login page.

Building the Login Page

Let's create a simple login page using Next.js components. Create a new file named login.js inside the pages directory. This file will contain the code for our login page. Here’s a basic implementation:

// pages/login.js
import { useState } from 'react';
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
const supabase = createClient(supabaseUrl, supabaseAnonKey);

export default function Login() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const handleLogin = async (e) => {
    e.preventDefault();
    setLoading(true);
    setError(null);

    try {
      const { user, error } = await supabase.auth.signIn({
        email: email,
        password: password,
      });

      if (error) {
        setError(error.message);
      } else {
        // Redirect to the home page or dashboard
        window.location.href = '/';
      }
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    
      <h1>Login</h1>
      {error && 
        {error}
      }
      
        Email:
        
      
      
        Password:
        
      
      
        Login
      
    
  );
}

In this code:

  • We import useState from React to manage the form inputs and loading state.
  • We initialize the Supabase client using the URL and anon key from our environment variables.
  • We define a Login component that renders a simple form with email and password inputs.
  • The handleLogin function is called when the form is submitted. It calls supabase.auth.signIn to authenticate the user with Supabase.
  • If the login is successful, we redirect the user to the home page. If there's an error, we display an error message.

Don't forget to create an index page or dashboard so that the redirect in the handleLogin function works correctly. For example, create pages/index.js:

// pages/index.js

export default function Home() {
  return (
    
      <h1>Welcome to the Home Page!</h1>
    
  );
}

Now, run your Next.js development server:

npm run dev

Navigate to http://localhost:3000/login in your browser, and you should see the login form. Try logging in with valid credentials. If everything is set up correctly, you'll be redirected to the home page.

Enhancing the Login Page

Okay, so we have a basic login page working. But, it's a bit bare-bones, isn't it? Let's look at some ways to enhance it.

Adding Sign-Up Functionality

Right now, users can only log in if they already have an account. Let's add a sign-up form to allow new users to create accounts. Add the following code to your login.js file:

// pages/login.js

// Add this state variable
const [isSignUp, setIsSignUp] = useState(false);

// Add this function to handle sign-up
const handleSignUp = async (e) => {
  e.preventDefault();
  setLoading(true);
  setError(null);

  try {
    const { user, error } = await supabase.auth.signUp({
      email: email,
      password: password,
    });

    if (error) {
      setError(error.message);
    } else {
      // Optionally, redirect to a verification page or the home page
      window.location.href = '/';
    }
  } catch (err) {
    setError(err.message);
  } finally {
    setLoading(false);
  }
};

// Modify the return statement to include the sign-up form
return (
  
    <h1>{isSignUp ? 'Sign Up' : 'Login'}</h1>
    {error && 
      {error}
    }
    
      Email:
      
    
    
      Password:
      
    
    
      {isSignUp ? 'Sign Up' : 'Login'}
    
    
      {isSignUp ? 'Already have an account? Login' : 'Need an account? Sign Up'}
    
  
);

In this code:

  • We add a isSignUp state variable to toggle between the login and sign-up forms.
  • We add a handleSignUp function that calls supabase.auth.signUp to create a new user account.
  • We modify the return statement to include both the login and sign-up forms, and a button to switch between them.

Implementing Social Login

Social login allows users to sign in with their existing accounts from providers like Google, Facebook, or GitHub. Supabase makes it incredibly easy to implement social login. Here’s how:

First, you need to enable the desired providers in your Supabase project settings. Go to the "Authentication" tab in your Supabase dashboard, then click on "Providers". Enable the providers you want to support and follow the instructions to configure them. You'll typically need to create an app in the provider's developer console and provide the app ID and secret to Supabase.

Once you've enabled the providers, you can add the following code to your login.js file:

// pages/login.js

// Add this function to handle social login
const handleSocialLogin = async (provider) => {
  setLoading(true);
  setError(null);

  try {
    const { user, session, error } = await supabase.auth.signIn({
      provider: provider,
    });

    if (error) {
      setError(error.message);
    } else {
      // Redirect to the home page or dashboard
      window.location.href = '/';
    }
  } catch (err) {
    setError(err.message);
  } finally {
    setLoading(false);
  }
};

// Modify the return statement to include the social login buttons
return (
  
    <h1>{isSignUp ? 'Sign Up' : 'Login'}</h1>
    {error && 
      {error}
    }
    
      Email:
      
    
    
      Password:
      
    
    
      {isSignUp ? 'Sign Up' : 'Login'}
    
    
      {isSignUp ? 'Already have an account? Login' : 'Need an account? Sign Up'}
    
    
      Sign in with Google
    
  
);

In this code:

  • We add a handleSocialLogin function that calls supabase.auth.signIn with the provider option to initiate the social login flow.
  • We add buttons for each social provider that call the handleSocialLogin function when clicked.

Adding Real-time Updates

To enhance the user experience, you can add real-time updates to your login page using Supabase's real-time capabilities. For example, you can display a list of online users or show a notification when a new user signs up.

First, you need to enable real-time updates in your Supabase project settings. Go to the "Database" tab in your Supabase dashboard, then click on "Realtime". Enable real-time updates for the tables you want to subscribe to.

Once you've enabled real-time updates, you can add the following code to your login.js file:

// pages/login.js
import { useEffect, useState } from 'react';

// Add this state variable
const [onlineUsers, setOnlineUsers] = useState([]);

// Add this useEffect hook to subscribe to real-time updates
useEffect(() => {
  const subscription = supabase
    .from('users')
    .on('*', (payload) => {
      // Update the list of online users
      setOnlineUsers((prevUsers) => {
        if (payload.new.online) {
          return [...prevUsers, payload.new];
        } else {
          return prevUsers.filter((user) => user.id !== payload.new.id);
        }
      });
    })
    .subscribe();

  // Clean up the subscription when the component unmounts
  return () => {
    supabase.removeSubscription(subscription);
  };
}, []);

// Modify the return statement to display the list of online users
return (
  
    <h1>{isSignUp ? 'Sign Up' : 'Login'}</h1>
    {error && 
      {error}
    }
    
      Email:
      
    
    
      Password:
      
    
    
      {isSignUp ? 'Sign Up' : 'Login'}
    
    
      {isSignUp ? 'Already have an account? Login' : 'Need an account? Sign Up'}
    
    
      Sign in with Google
    
    
      <h2>Online Users</h2>
      
        {onlineUsers.map((user) => (
          {user.email}
        ))}
      
    
  
);

In this code:

  • We add a onlineUsers state variable to store the list of online users.
  • We add a useEffect hook to subscribe to real-time updates from the users table.
  • The useEffect hook updates the onlineUsers state variable whenever a user comes online or goes offline.
  • We modify the return statement to display the list of online users.

Conclusion

Alright, awesome work, guys! You've successfully built a Supabase login page with Next.js. We covered everything from setting up your Next.js project and Supabase, to implementing the login form, social login, and real-time updates. Now you have a solid foundation for building more complex authentication flows and user experiences. Keep experimenting, and don't be afraid to dive deeper into the Supabase and Next.js documentation. You're on your way to creating some truly amazing web apps!