惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
NISL@THU
NISL@THU
T
Threatpost
T
The Exploit Database - CXSecurity.com
T
Threat Research - Cisco Blogs
S
Securelist
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
S
Secure Thoughts
MyScale Blog
MyScale Blog
O
OpenAI News
P
Palo Alto Networks Blog
美团技术团队
C
Cyber Attacks, Cyber Crime and Cyber Security
TaoSecurity Blog
TaoSecurity Blog
量子位
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tailwind CSS Blog
Know Your Adversary
Know Your Adversary
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Simon Willison's Weblog
Simon Willison's Weblog
宝玉的分享
宝玉的分享
PCI Perspectives
PCI Perspectives
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
I
InfoQ
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
S
Security @ Cisco Blogs
S
Schneier on Security
B
Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Cloudflare Blog
AWS News Blog
AWS News Blog
IT之家
IT之家
V
Vulnerabilities – Threatpost
The Hacker News
The Hacker News
H
Heimdal Security Blog
I
Intezer
A
Arctic Wolf
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Help Net Security
W
WeLiveSecurity

Clerk Blog

Going to production with Clerk Deploy Clerk Init: The fastest way to start a new project Introducing Clerk CLI Middleware-based route protection bypass Postmortem: Clerk System Outage (March 10, 2026) Clerk for the AI era Add API Key support to your SaaS in minutes Postmortem: Clerk System Outage (February 19, 2026) Using Clerk in a React Native app Postmortem: DNS Provider Outage (February 10, 2026) How do I implement passkeys in Next.js? Clerk ranked #4 fastest-growing software vendor on Ramp’s December 2025 list How do I handle JWT verification in Next.js? Committing to Agent Identity: Clerk raises $50m Series C from Menlo and Anthropic’s Anthology Fund What is the best way to handle authentication in Next.js App Router? Postmortem: Database Incident (September 14–18, 2025) How do I add authentication to a Next.js app? Introducing Free Trials in Clerk Billing Postmortem: August 28, 2025 - elevated API latency and errors Introducing Mosaic: Bring Your Brand to Every Authentication Flow Multi-tenant authentication: What you need to know (and how Clerk helps) What are the risks and challenges of multi-tenancy? Resilience in Practice: Regional Failover at Clerk Build a Cross-Platform B2B App with Clerk, Expo, and Supabase Highlights from the MiduDev/Clerk Hackathon Add multi-tenancy to an app built with Clerk, Lovable, and Supabase How to build an AI coding rules app with Clerk, Lovable, and Supabase How to Build Multi-Tenant Authentication with Clerk Choosing the right SaaS architecture: Multi-Tenant vs. Single-Tenant Postmortem: June 26, 2025 service outage How to Design a Multi-Tenant SaaS Architecture What is multi-tenancy and why it matters for B2B SaaS How OAuth Works Synchronize user data from Clerk to Supabase Add subscriptions to your SaaS with Clerk Billing Getting started with Clerk Billing Multi-tenant analytics with Tinybird and Clerk How Huntr Migrated 250K Users to Clerk: A Scalable Auth Solution for Startups How to take Clerk to Production How to take your Clerk application to production A practical guide to testing Clerk Next.js applications Implementing multi-tenancy into a Supabase app with Clerk How Clerk integrates with a Next.js application using Supabase How Clerk integrates with Supabase Build a blog with tRPC, Prisma, Next.js and Clerk How to enrich PostHog events with Clerk user data How to build a secure project management platform with Next.js, Clerk, and Neon Validate your SaaS idea while building an audience Postmortem: February 6, 2025 service outage Implement Role-Based Access Control in Next.js 15 Build a Next.js sign-up form with React Hook Form Build a Next.js login page template How to implement Google authentication in Next.js 15 What is middleware in Next.js? How to customize Next.js metadata How to set environment variables in Node.js Building a React Login Page Template How to implement per-user OAuth scopes with Clerk Using Clerk SSO to access Google Calendar and other service data Streamline enterprise customer onboarding with SAML and Clerk Clerk launches EASIE SSO and eliminates SSO fees How to secure Liveblocks Rooms with Clerk in Next.js Securing Node.js Express APIs with Clerk and React Combining the benefits of session tokens and JWTs Comparing Clerk Webhooks vs Backend API Automate Neon schema changes with Drizzle and GitHub Actions A guide to reading authenticated user data from Clerk Role based access control with Clerk Organizations Mitigating OAuth’s recently discovered Open Response Type vulnerability Per-user B2B monetization with Stripe and Clerk Organizations Build a team-based task manager with Next.js, Neon, and Clerk Building a Hybrid Sign-Up/Subscribe Form with Stripe Elements Welcoming Colin from Zod as our inaugural Open Source Fellow Build a modern authenticated chat application with Next.js, Ably, and Clerk Build a waitlist with Clerk user metadata How to use Clerk with PostHog Identify in Next.js How to secure API Gateway using JWT and Lambda Authorizers with Clerk What are passkeys and how do they work? Comparing Authentication in React.js vs. Next.js How to Add an Onboarding Flow for your Application with Clerk Create Your Own Custom User Menu with Radix - Part 2 Introducing Webhook Workflows with Inngest & Svix Clerk raises $30M Series B from CRV and Stripe Clerk in 2023: A Year in Review Build a Movie Emoji Quiz App with Remix, Fauna, and Clerk Ultimate Guide to Magic Link Authentication Create Your Own Custom User Menu with Radix Introducing has(), protect(), and <Protect> Updated Pricing: 10,000 MAUs Free, and a new “Pro Plan” Next.js Authentication with Clerk: Streamlined SSR Handling Clerk Webhooks: Data Sync with Convex Exploring Clerk Metadata with Stripe Webhooks The Ultimate Guide to Next.js Authentication Empower Your Support Team With User Impersonation Clerk Webhooks: Getting Started A Complete Guide to Session Management in Next.js The Advanced Guide to Passwordless Authentication in Next.js How We Roll – Chapter 10: Roundup How We Roll – Chapter 9: Infrastructure Password-Based Authentication in Next.js
Build a task manager with Next.js, Supabase, and Clerk
Alexis Aguilar · 2024-09-06 · via Clerk Blog

Supabase is an open-source backend-as-a-service platform that provides Postgres databases, authentication, instant APIs, realtime data subscriptions, and more to help developers quickly build scalable applications.

Integrating Supabase with Clerk gives you the benefits of using a Supabase database while leveraging Clerk's Next.js authentication, prebuilt components, and webhooks.

To get the most out of Supabase with Clerk, you must implement custom Row Level Security (RLS) policies. RLS works by validating database queries according to the restrictions defined in the RLS policies applied to the table. This guide will show you how to create RLS policies that restrict access to data based on the user's Clerk ID. This way, users can only access data that belongs to them. To set this up, you will:

  • Create a function in Supabase to parse the Clerk user ID from the authentication token.
  • Create a user_id column that defaults to the Clerk user's ID when new records are created.
  • Create policies to restrict what data can be read, inserted, updated, and deleted.
  • Use the Clerk Supabase integration helper in your code to authenticate with Supabase and execute queries.

This guide will have you create a new table in your Supabase project, but once you've learned the concepts and the process, you can apply them to any existing table.

The source code for the final version can be found here.

If you're wondering how this project was created, check out the Next.js quickstart.

Set up a Clerk project

If you do not have a Clerk account, create one before proceeding. If you already have an account, create a new project for this guide.

Once you create an application, you'll be presented with the quickstarts. For this guide, follow the Next.js quickstart and only complete step 2, which instructs you to create the .env.local file and populate it with the necessary environment variables. The remaining steps are already completed as part of the quickstart repository that you cloned in the previous step.

Run your project with the following command:

Visit your app's homepage at http://localhost:3000. Sign up to create your first user and test everything works as expected.

Set up a Supabase project

If you do not have a Supabase account, create one before proceeding. If you already have an account, create a new project in the Supabase dashboard.

Create a SQL query that checks the user's Clerk ID

Now that you've set up your project, it's time to get to work.

Create a function named requesting_user_id() that will parse the Clerk user ID from the authentication token. This function will be used to set the default value of user_id in a table and in the RLS policies to ensure the user can only access their data.

  1. In the sidebar of your Supabase dashboard, navigate to SQL Editor. This is where you will run all your SQL queries for the rest of this guide. Paste the following into the editor:
  2. To execute the query and create the requesting_user_id() function, select Run. The results will be displayed in the Results tab, and should say "Success. No rows returned". Throughout this guide, keep an eye on this tab when running queries as it will display any errors that occur.

Create a table and enable RLS on it

Next, you'll create a "tasks" table and enable RLS on that table. The "tasks" table will also contain a user_id column that will use the requesting_user_id() function you just created as its default value. This column will be used in the RLS policies to only return or modify records scoped to the user's account.

To create the "tasks" table and enable RLS on it, you'll run the following two queries. The first query creates the table and the second query enables RLS on the table.

Paste the following in the SQL Editor and select Run:

If you want to see the table you just created, in the sidebar, select Table Editor and select the "tasks" table. You should see three empty columns: id, name, and user_id.

Create ID-based RLS policies

Now, you need to create RLS policies that permit users to read, insert, update, and delete content associated with their user IDs only.

Paste the following in the SQL Editor and select Run:

Get your Supabase JWT secret key

Now that your table is set up and ready to be populated with data, it's time to set up your Clerk application and get Supabase integrated.

Get your Supabase JWT secret key:

  1. In the sidebar, navigate to Project Settings > API.
  2. Under the JWT Settings section, save the value in the JWT Secret field somewhere secure. This value will be used in the next step.

Create a Supabase JWT template

When sending requests to Supabase, Supabase needs to verify that the user is who they say they are. Because you're using Clerk to authenticate your users, you need Clerk to tell Supabase who the user is. This is where JWTs come in. For each authenticated user, Clerk issues JWTs that contain information about the user, like their ID. You're going to create a custom template for a JWT that Supabase can use.

To create a JWT template for Supabase:

  1. Navigate to the Clerk Dashboard.
  2. In the navigation sidebar, select JWT Templates.
  3. Select the New template button, then select Supabase from the list of options.
  4. Configure your template:
    • The value of the Name field will be required when using the template in your code. For this tutorial, name it supabase.
    • Signing algorithm will be HS256 by default. This algorithm is required to use JWTs with Supabase. Learn more in their docs.
    • Under Signing key, add the value of your Supabase JWT secret key from the previous step.
    • You can leave all other fields at their default settings or customize them to your needs. See the JWT template guide to learn more about these settings.
    • Select Save from the notification bubble to complete setup.

Install the Supabase client library

Add the Supabase client library to your project by running the following command in your terminal:

terminal

Set up your environment variables

Add the Supabase project URL and key to your .env.local file.

  1. In the sidebar of the Supabase dashboard, select Settings > API.
  2. Add the Project URL to your .env.local file as SUPABASE_URL.
  3. In the Project API keys section, add the value beside anon public to your .env.local file as SUPABASE_KEY.

Fetch Supabase data in your code

Let's get to coding!

You want to load a list of tasks for the user and allow the user to add new tasks, mark tasks as complete, and delete tasks. You can do this either on the client-side or server-side.

Client-side rendering (CSR)

The following example demonstrates how to fetch data from Supabase in a client-side rendered page.

The createClerkSupabaseClient() function uses Supabase's createClient() method to initialize a new Supabase client, but modifies it to inject the Clerk token you created with the Supabase JWT template into the request headers sent to Supabase. The requesting_user_id() function that was created in the Supabase dashboard will parse the user ID from the Clerk token and use it when querying data from the tasks table.

Paste the following code into the app/page.tsx file:

app/page.tsx

Server-side rendering (SSR)

The following example demonstrates how to fetch data from Supabase in a server-side rendered page. It requires creating multiple files as you will use Server Actions to handle adding, deleting, and updating tasks.

The createClerkSupabaseClientSsr() function uses Supabase's createClient() method to initialize a new Supabase client, but modifies it to inject the Clerk token you created with the Supabase JWT template into the request headers sent to Supabase. The requesting_user_id() function that was created in the Supabase dashboard will parse the user ID from the Clerk token and use it when querying data from the tasks table.

It is stored in a separate file so that it can be reused in multiple places, such as in both your page.tsx and your Server Action file.

Create the src/app/ssr/client.ts file and paste the following code into it:

src/app/ssr/client.ts

Create the src/app/ssr/page.tsx file and paste the following code into it:

src/app/ssr/page.tsx

Create a src/app/ssr/actions.ts file which will include Server Actions for adding, deleting, and updating tasks. Paste the following code into that file:

src/app/ssr/actions.ts

Your form for adding tasks will use the addTask() Server Action that you created in the previous file. The form is in a separate file than your page.tsx file because it must be a client component. Create the src/app/ssr/AddTaskForm.tsx file and paste the following code into it:

src/app/ssr/AddTaskForm.tsx

Create the src/app/ssr/TaskRow.tsx file which will display the tasks in your list. It's a separate file from your page.tsx because it uses the useRouter() hook, so it must be a client component. Paste the following code into that file:

src/app/ssr/TaskRow.tsx

Test your integration

Now it's time to test your code.

Run your project with the following command:

Sign in and test viewing, creating, updating, and deleting tasks. Sign out and sign in as a different user, and repeat.

If you have the same tasks across multiple accounts, double-check that RLS is enabled, or that the RLS policies were properly created. Check the table in the Supabase dashboard. You should see all the tasks between both users but with differing values in the user_id column.