Skip to content

Commit d94f1ce

Browse files
authored
Merge pull request #4 from clerk/brk.chore/supabase-integration-2
chord: Update template based on new guide
2 parents ab903c8 + bd16ae6 commit d94f1ce

File tree

7 files changed

+663
-319
lines changed

7 files changed

+663
-319
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@
3434
Integrating Supabase with Clerk gives you the benefits of using a Supabase database while leveraging Clerk's authentication, prebuilt components, and webhooks. To get the most out of Supabase with Clerk, you must implement custom [Row Level Security](https://supabase.com/docs/guides/auth/row-level-security) (RLS) policies.
3535

3636
After following [the Clerk + Supabase integration guide](https://clerk.com/docs/integrations/databases/supabase), you will have learned how to:
37-
- 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.
38-
- Configure Supabase to accept JWTs from Clerk
39-
- Create a JWT template in Clerk to generate Supabase JWTs
40-
- Use the Supabase JWTs to authenticate Supabase queries in your Next.js app
37+
38+
- Enable the Supabase integration on your Clerk instance
39+
- 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.
40+
- Configure Clerk as a Supabase third-party auth provider
41+
- Use Clerk JWTs to authenticate Supabase queries in your Next.js app
4142

4243
## Deploy
4344

@@ -83,4 +84,3 @@ Feel free to create a support thread on our [Discord](https://clerk.com/discord)
8384
You can discuss ideas, ask questions, and meet others from the community in our [Discord](https://discord.com/invite/b5rXHjAg7A).
8485

8586
If you prefer, you can also find support through our [Twitter](https://twitter.com/ClerkDev), or you can [email](mailto:[email protected]) us!
86-

app/page.tsx

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
'use client';
2-
import { useEffect, useState } from 'react';
3-
import { useSession, useUser } from '@clerk/nextjs';
4-
import { createClient } from '@supabase/supabase-js';
1+
"use client";
2+
import { useEffect, useState } from "react";
3+
import { useSession, useUser } from "@clerk/nextjs";
4+
import { createClient } from "@supabase/supabase-js";
55

66
export default function Home() {
77
const [tasks, setTasks] = useState<any[]>([]);
88
const [loading, setLoading] = useState(true);
9-
const [name, setName] = useState('');
9+
const [name, setName] = useState("");
1010
// The `useUser()` hook will be used to ensure that Clerk has loaded data about the logged in user
1111
const { user } = useUser();
1212
// The `useSession()` hook will be used to get the Clerk session object
@@ -18,23 +18,8 @@ export default function Home() {
1818
process.env.NEXT_PUBLIC_SUPABASE_URL!,
1919
process.env.NEXT_PUBLIC_SUPABASE_KEY!,
2020
{
21-
global: {
22-
// Get the custom Supabase token from Clerk
23-
fetch: async (url, options = {}) => {
24-
const clerkToken = await session?.getToken({
25-
template: 'supabase',
26-
});
27-
28-
// Insert the Clerk Supabase token into the headers
29-
const headers = new Headers(options?.headers);
30-
headers.set('Authorization', `Bearer ${clerkToken}`);
31-
32-
// Now call the default fetch
33-
return fetch(url, {
34-
...options,
35-
headers,
36-
});
37-
},
21+
async accessToken() {
22+
return session?.getToken() ?? null;
3823
},
3924
}
4025
);
@@ -50,7 +35,7 @@ export default function Home() {
5035

5136
async function loadTasks() {
5237
setLoading(true);
53-
const { data, error } = await client.from('tasks').select();
38+
const { data, error } = await client.from("tasks").select();
5439
if (!error) setTasks(data);
5540
setLoading(false);
5641
}
@@ -61,7 +46,7 @@ export default function Home() {
6146
async function createTask(e: React.FormEvent<HTMLFormElement>) {
6247
e.preventDefault();
6348
// Insert task into the "tasks" database
64-
await client.from('tasks').insert({
49+
await client.from("tasks").insert({
6550
name,
6651
});
6752
window.location.reload();
@@ -75,7 +60,7 @@ export default function Home() {
7560

7661
{!loading &&
7762
tasks.length > 0 &&
78-
tasks.map((task: any) => <p>{task.name}</p>)}
63+
tasks.map((task: any) => <p key={task.id}>{task.name}</p>)}
7964

8065
{!loading && tasks.length === 0 && <p>No tasks found</p>}
8166

app/ssr/actions.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
'use server';
1+
"use server";
22

3-
import { createClerkSupabaseClientSsr } from './client';
3+
import { createServerSupabaseClient } from "./client";
44

5-
const client = createClerkSupabaseClientSsr();
5+
const client = createServerSupabaseClient();
66

77
export async function addTask(name: string) {
88
try {
9-
const response = await client.from('tasks').insert({
9+
const response = await client.from("tasks").insert({
1010
name,
1111
});
1212

13-
console.log('Task successfully added!', response);
13+
console.log("Task successfully added!", response);
1414
} catch (error: any) {
15-
console.error('Error adding task:', error.message);
16-
throw new Error('Failed to add task');
15+
console.error("Error adding task:", error.message);
16+
throw new Error("Failed to add task");
1717
}
1818
}

app/ssr/client.tsx

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,13 @@
1-
import { auth } from '@clerk/nextjs/server';
2-
import { createClient } from '@supabase/supabase-js';
3-
4-
export function createClerkSupabaseClientSsr() {
5-
// The `useAuth()` hook is used to access the `getToken()` method
6-
const { getToken } = auth();
1+
import { auth } from "@clerk/nextjs/server";
2+
import { createClient } from "@supabase/supabase-js";
73

4+
export function createServerSupabaseClient() {
85
return createClient(
96
process.env.NEXT_PUBLIC_SUPABASE_URL!,
107
process.env.NEXT_PUBLIC_SUPABASE_KEY!,
118
{
12-
global: {
13-
// Get the custom Supabase token from Clerk
14-
fetch: async (url, options = {}) => {
15-
const clerkToken = await getToken({
16-
template: 'supabase',
17-
});
18-
19-
// Insert the Clerk Supabase token into the headers
20-
const headers = new Headers(options?.headers);
21-
headers.set('Authorization', `Bearer ${clerkToken}`);
22-
23-
// Now call the default fetch
24-
return fetch(url, {
25-
...options,
26-
headers,
27-
});
28-
},
9+
async accessToken() {
10+
return (await auth()).getToken();
2911
},
3012
}
3113
);

app/ssr/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { createClerkSupabaseClientSsr } from './client';
2-
import AddTaskForm from './AddTaskForm';
1+
import { createServerSupabaseClient } from "./client";
2+
import AddTaskForm from "./AddTaskForm";
33

44
export default async function Home() {
55
// Use the custom Supabase client you created
6-
const client = createClerkSupabaseClientSsr();
6+
const client = createServerSupabaseClient();
77

88
// Query the 'tasks' table to render the list of tasks
9-
const { data, error } = await client.from('tasks').select();
9+
const { data, error } = await client.from("tasks").select();
1010
if (error) {
1111
throw error;
1212
}
@@ -18,7 +18,7 @@ export default async function Home() {
1818

1919
<div>
2020
{tasks?.map((task: any) => (
21-
<p>{task.name}</p>
21+
<p key={task.id}>{task.name}</p>
2222
))}
2323
</div>
2424

0 commit comments

Comments
 (0)