Create a Plasmic App using Supabase Auth with Userbased Database Access.

Shams⚡️Nahid
4 min readSep 9, 2024

In this Breakdown, I walk you through setting up a local server to host Plasmic, and show you how to integrate Supabase Authentication for user-based table access with relations to POST/GET data and CRUD functionalities. This beginner-friendly tutorial is the only one available online that addresses the Supabase-Plasmic authentication integration. I’ve included all the necessary details and steps to ensure a smooth setup process.

However, if you encounter any issues, feel free to reach out to me at contact@shams.digital.

Big Thanks to Callum Boase Brother for his powerful Package.

First Check This Video, then follow all steps below:

  • Open VS Code Terminal, and run this, and do the rest of the setup as I showed on my breakdown video.
npx create-plasmic-app
  • Setup Custom App Host as shown.

2. Supabase Setup

Set up your supabase project as shown.

3. Setup Plasmic Auth using Supabase on VS Code

  • In the terminal, run npm install to install Plasmic & it's dependencies
  • Add a .env.local file with your supabase credentials (from Supabase dashboard)
# Supabase Project
NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

. npm install plasmic-supabase to install this package

  • Open ./plasmic-init.ts. It should look like this to start with (default Plasmic comments removed for brevity)
  • Modify plasmic-init.ts to import components from plasmic-supabase
import { initPlasmicLoader } from "@plasmicapp/loader-nextjs";
import {
SupabaseProvider,
SupabaseProviderMeta,
SupabaseUserGlobalContext,
SupabaseUserGlobalContextMeta,
SupabaseUppyUploader,
SupabaseUppyUploaderMeta,
SupabaseStorageGetSignedUrl,
SupabaseStorageGetSignedUrlMeta,
} from "plasmic-supabase"

export const PLASMIC = initPlasmicLoader({
projects: [
{
id: "your-plasmic-project-id",
token: "your-plasmic-project-token",
},
],

preview: true,
});

//Register global context
PLASMIC.registerGlobalContext(SupabaseUserGlobalContext, SupabaseUserGlobalContextMeta)

//Register components
PLASMIC.registerComponent(SupabaseProvider, SupabaseProviderMeta);
PLASMIC.registerComponent(SupabaseUppyUploader, SupabaseUppyUploaderMeta);
PLASMIC.registerComponent(SupabaseStorageGetSignedUrl, SupabaseStorageGetSignedUrlMeta);
  • In ./pages directory add a new file called _app.tsx and add the following content. Save your file
import type { AppProps } from 'next/app';

//Import the CSS required for SupabaseUppyUploader globally
import "@uppy/core/dist/style.min.css";
import "@uppy/dashboard/dist/style.min.css";

function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}

export default MyApp;
  • In terminal: npm run dev to start your Dev server

4. Setup Plasmic Home, Login, Signup pages

  • Create Pages and Necessary Forms for auth. Watch the Breakdown video.
  • Test your auth functionalities by signing up and logging in.

5. Setup plasmic Secret pages by ensuring supabase Middleware

  • Install the package @supabase/ssr by running in terminal
npm install @supabase/ssr
  • Add to the root directory a file called middleware.ts with the following content:
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'

// Define the route that contains your login page
const loginPage = '/login'

// Add any public (non-login protected) routes here
// All other routes will be login protected
// Important: plasmic-host and your login page must always be public
const publicRoutes = [
'/',
'/login',
'/plasmic-host'
]

// Middleware function
// This will run on every request to your app that matches the pattern at the bottom of this file
// Adapted from @supabase/ssr docs https://supabase.com/docs/guides/auth/server-side/nextjs?queryGroups=router&router=app
export async function middleware(request: NextRequest) {

let supabaseResponse = NextResponse.next({
request,
})

//Create a new supabase client
//Refresh expired auth tokens and set new cookies
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
supabaseResponse = NextResponse.next({
request,
})
cookiesToSet.forEach(({ name, value, options }) =>
supabaseResponse.cookies.set(name, value, options)
)
},
},
}
)

// IMPORTANT: Avoid writing any logic between createServerClient and
// supabase.auth.getUser(). A simple mistake could make it very hard to debug
// issues with users being randomly logged out.

// Get details of the logged in user if present
const {
data: { user },
} = await supabase.auth.getUser()

// Decide whether to redirect to the /login page or not
// You can adapt this logic to suit your needs

if (publicRoutes.includes(request.nextUrl.pathname) !== true && !user) {
// It's a login protected route but there's no logged in user.
// Respond by redirecting the user to the login page
const url = request.nextUrl.clone()
url.pathname = loginPage;
return NextResponse.redirect(url)

} else {
// It's a public route, or it's a login protected route and there is a logged in user.
// Proceed as normal
return supabaseResponse
}

// IMPORTANT: You *must* return the supabaseResponse object as it is. If you're
// creating a new response object with NextResponse.next() make sure to:
// 1. Pass the request in it, like so:
// const myNewResponse = NextResponse.next({ request })
// 2. Copy over the cookies, like so:
// myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
// 3. Change the myNewResponse object to fit your needs, but avoid changing
// the cookies!
// 4. Finally:
// return myNewResponse
// If this is not done, you may be causing the browser and server to go out
// of sync and terminate the user's session prematurely!

}

//Only run middleware on requests that match this pattern
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* Feel free to modify this pattern to include more paths.
*/
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
}
npm run build
npm run start

6. Fetch data From Supabase

Watch Breakdown Video.

For adding row based value based on userid

{id: $ctx.SupabaseUser.user.id,
name:$state.nameInput.value}

--

--

Shams⚡️Nahid
Shams⚡️Nahid

No responses yet