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:

Let's add them in an .env file:

.env
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.ts:

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
)

Adding Redirect URL

When a user signs up, they'll need to confirm their email. To do this, we need to add a redirect URL to our Supabase project.

First, we need to create a consistent ID for our extension for development. When you push to the different web stores, you'll get a different ID. To learn more about how all of this works, check out our blog post on creating consistent extension IDs (opens in a new tab)

Go to the Itero KeyPair Tool (opens in a new tab) to generate your consistent extension ID.

We can store the ID and public key in our .env file:

.env
CRX_ID="Replace with the value of CRX ID from Itero KeyPair tool"
CRX_KEY="Replace with the value of Public Key from Itero KeyPair tool"

Then, references the public key in your package.json under the manifest.key value:

"manifest": {
    "host_permissions": [
      "https://*/*"
    ],
    "key": "$CRX_KEY",

Now we need to make it so that the browser doesn't block access to our options page. To do this, we must add it to our web_accessible_resources in our manifest:

"web_accessible_resources": [
      {
        "resources": [
          "options.html"
        ],
        "matches": [
          "<all_urls>"
        ],
        "extension_ids": [
          "$CRX_ID"
        ]
      }
    ]

Head over to the Supabase console and click on the "Authentication" tab, and click URL Configuration.

Now add the following URL in your site URL as well as your redirect URL:

chrome-extension://<CRX_ID>/options.html

Replace CRX_ID with the generated extension ID given to you by Itero KeyPairs tool, or the actual ID given to you by the production web store.

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,
        data: { user, session }
      } =
        type === "LOGIN"
          ? await supabase.auth.signInWithPassword({
              email: username,
              password
            })
          : await supabase.auth.signUp({ email: username, password })
 
      if (error) {
        alert("Error with auth: " + error.message)
      } else if (!user) {
        alert("Signup successful, confirmation mail should be sent soon!")
      } else {
        setUser(user)
      }
    } 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!