Create a Plasmic App using Supabase Auth with Userbased Database Access.
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 fromplasmic-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}