DEV Community

Cover image for Getting Started with Supabase in a React + TypeScript App: Authentication Basics
Sukanta Biswas
Sukanta Biswas

Posted on

Getting Started with Supabase in a React + TypeScript App: Authentication Basics

I recently came across Supabase, and I have to say I’m really excited about it. Supabase is a Backend-as-a-Service (BaaS) that provides authentication, a Postgres database, real-time subscriptions, and storage right out of the box. What I like the most is how simple it is to learn and how seamlessly it integrates with a React project.

This is the first post in a series on Supabase integration with React. I'll keep things as simple as possible, starting with the basics: setting up a React + TypeScript project, connecting it to Supabase, and building a clean authentication flow with signup, login, and logout, styled using TailwindCSS.


Setting up Supabase

  1. Go to supabase.com and sign up.
  2. Create a new project. Once it's ready, note down your Project URL and anon API key from the dashboard.
  3. In the Authentication settings, enable Email/Password login.

Creating a React + TypeScript Project

We'll start fresh with Vite.

npx create-vite@latest supabase-auth-demo --template react-ts
cd supabase-auth-demo
npm install
npm install @supabase/supabase-js tailwindcss postcss autoprefixer
npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

Set up Tailwind in tailwind.config.js:

content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
  extend: {},
},
plugins: [],
Enter fullscreen mode Exit fullscreen mode

Add Tailwind to src/index.css:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Initializing Supabase

Create a new file src/supabaseClient.ts:

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

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL as string;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY as string;

export const supabase = createClient(supabaseUrl, supabaseAnonKey);
Enter fullscreen mode Exit fullscreen mode

Add your Supabase credentials to .env:

VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
Enter fullscreen mode Exit fullscreen mode

Building the Authentication UI

We'll build a simple form with React and TailwindCSS for signup, login, and logout.

import { useState } from "react";
import { supabase } from "./supabaseClient";

export default function Auth() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [user, setUser] = useState<any>(null);
  const [error, setError] = useState("");

  const handleSignup = async () => {
    const { data, error } = await supabase.auth.signUp({ email, password });
    if (error) setError(error.message);
    else setUser(data.user);
  };

  const handleLogin = async () => {
    const { data, error } = await supabase.auth.signInWithPassword({ email, password });
    if (error) setError(error.message);
    else setUser(data.user);
  };

  const handleLogout = async () => {
    await supabase.auth.signOut();
    setUser(null);
  };

  return (
    <div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
      <div className="bg-white shadow-md rounded-lg p-6 w-80">
        <h2 className="text-2xl font-bold text-center mb-4">Supabase Auth</h2>
        {error && <p className="text-red-500 text-sm mb-2">{error}</p>}

        {!user ? (
          <>
            <input
              type="email"
              placeholder="Email"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
              className="w-full mb-3 px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
            />
            <input
              type="password"
              placeholder="Password"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              className="w-full mb-3 px-3 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
            />
            <div className="flex gap-2">
              <button
                onClick={handleSignup}
                className="w-1/2 bg-blue-600 text-white py-2 rounded-lg hover:bg-blue-700"
              >
                Sign Up
              </button>
              <button
                onClick={handleLogin}
                className="w-1/2 bg-green-600 text-white py-2 rounded-lg hover:bg-green-700"
              >
                Login
              </button>
            </div>
          </>
        ) : (
          <div className="text-center">
            <p className="mb-4">Logged in as {user.email}</p>
            <button
              onClick={handleLogout}
              className="w-full bg-red-600 text-white py-2 rounded-lg hover:bg-red-700"
            >
              Logout
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Persisting the User Session

You can fetch the current session when the app loads:

import { useEffect } from "react";

useEffect(() => {
  supabase.auth.getSession().then(({ data }) => {
    console.log("Session:", data.session);
  });
}, []);

Enter fullscreen mode Exit fullscreen mode

Wrapping Up

We just set up a Supabase-powered authentication system in React with TypeScript, complete with signup, login, and logout, all styled using TailwindCSS. This is a solid starting point for any app that needs user authentication.

In the next part of this series, we'll explore Supabase Edge Functions and how to build custom APIs for your application.
If you found this post valuable, consider sharing it with others who might benefit from it as well!

Top comments (0)