Quickstart: Supabase

Quickstart with Supabase

Intro

Supabase is an open-source Firebase alternative.

This quickstart is a simple example showcasing how to use Supabase with Plasmo.

Prerequisites

Set up Environment Variables

For Supabase to work, we'll need to define a URL and a KEY.

You can find these by finding them in your Supabase project dashboard:

We need to declare a ProcessEnv namespace for our environment variables so that IntelliSense will work.

index.d.ts

index.d.ts
declare namespace NodeJS {
  interface ProcessEnv {
    PLASMO_PUBLIC_SUPABASE_URL?: string
    PLASMO_PUBLIC_SUPABASE_KEY?: string
  }
}
.env.local
PLASMO_PUBLIC_SUPABASE_URL="CHANGE ME"
PLASMO_PUBLIC_SUPABASE_KEY="CHANGE ME"

Supabase Store

We need to initialize Supabase, so let's add a file called store.

core/store.ts
import { createClient } from "@supabase/supabase-js"
 
export const supabase = createClient(
  process.env.PLASMO_PUBLIC_SUPABASE_URL,
  process.env.PLASMO_PUBLIC_SUPABASE_KEY
)

Integrating with a React component

Now we can write code in our React components utilizing Supabase!

Here's an example of using Supabase in a React component for the extension's options page.

options.tsx
import type { User } from "@supabase/supabase-js"
import { useState } from "react"
 
import { supabase } from "~core/store"
 
function IndexOptions() {
  const [username, setUsername] = useState("")
  const [password, setPassword] = useState("")
 
  const [user, setUser] = useState<User>(null)
 
  const handleLogin = async (
    type: "LOGIN" | "SIGNUP",
    username: string,
    password: string
  ) => {
    try {
      const { error, user: signedInUser } =
        type === "LOGIN"
          ? await supabase.auth.signIn(
              { email: username, password },
              {
                redirectTo: window.location.href
              }
            )
          : await supabase.auth.signUp(
              { email: username, password },
              {
                redirectTo: window.location.href
              }
            )
 
      if (error) {
        alert("Error with auth: " + error.message)
      } else if (!signedInUser) {
        alert("Signup successful, confirmation mail should be sent soon!")
      } else {
        setUser(signedInUser)
      }
    } catch (error) {
      console.log("error", error)
      alert(error.error_description || error)
    }
  }
 
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        padding: 16
      }}>
      {user && (
        <div>
          {user.email} - {user.id}
        </div>
      )}
      {!user && (
        <div>
          <div className="mb-4">
            <label className="font-bold text-grey-darker block mb-2">
              Email
            </label>
            <input
              type="text"
              placeholder="Your Username"
              value={username}
              onChange={(e) => setUsername(e.target.value)}
            />
          </div>
          <div className="mb-4">
            <label className="font-bold text-grey-darker block mb-2">
              Password
            </label>
            <input
              type="password"
              placeholder="Your password"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
            />
          </div>
 
          <div className="flex flex-col gap-2">
            <button
              onClick={(e) => {
                e.preventDefault()
                handleLogin("SIGNUP", username, password)
              }}
              className="bg-indigo-700 hover:bg-teal text-white py-2 px-4 rounded text-center transition duration-150 hover:bg-indigo-600 hover:text-white">
              Sign up
            </button>
            <button
              onClick={(e) => {
                e.preventDefault()
                handleLogin("LOGIN", username, password)
              }}
              className="border border-indigo-700 text-indigo-700 py-2 px-4 rounded w-full text-center transition duration-150 hover:bg-indigo-700 hover:text-white">
              Login
            </button>
          </div>
        </div>
      )}
    </div>
  )
}
 
export default IndexOptions

Full Example

To see a complete example, check out with-supabase (opens in a new tab) in our examples repo!

Last updated on December 27, 2022