Skip to main content
Week 03 • Track 02 • The Tool

The Backend
Conductor.

You don't need to memorize SQL. You just need to know how to ask for it. Use AI to synthesize the connection between your UI and Supabase.

AI

The Mental Model

React is the Keyboard.
Supabase is the Engine.

A synthesizer makes no sound until you patch the keyboard voltage to the oscillator. In our stack, the Custom Hook is the patch cable.

1

The Database (Supabase): Stores the raw data (The Sound Source).

2

The AI (Cursor/Claude): Writes the wiring code (The Technician).

3

The Hook (useData): Brings the data into the component (The Cable).

Postgres
UI

The Baton

Key Skill
Context Loading

Don't ask blindly.

AI doesn't know you're using Supabase unless you tell it. Before asking for a hook, you must load the context.

The "System Prompt" Trick

"I am building a Next.js 15 app with Tailwind and Supabase. I am using the @/lib/supabase/client file for connection."

Bad

"Write code to fetch users."

Good

"Create a React hook called useUsers. Use the Supabase client from @/lib/supabase. Fetch from the 'users' table. Handle loading and error states. Return an object."

hooks/useUsers.ts
import { createClient } from "@/utils/supabase/client";

export function useUsers() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchUsers = async () => {
      const supabase = createClient();
      const { data, error } = await supabase
        .from("users")
        .select("*");
      // AI handles the boring error checking for you
      if (!error) setData(data);
      setLoading(false);
    };
    fetchUsers();
  }, []);

  return { data, loading };
}

The Gatekeeper

Row Level Security.

By default, Supabase is like an open club. Anyone with the URL can walk in. RLS (Row Level Security) is the bouncer.

X

Without RLS: Anyone can DELETE your users.

With RLS: Users only see their own data.

The Prompt to Fix It

"Write a Supabase RLS policy that only allows authenticated users to insert rows into the 'todos' table."
auth.uid() = user_id

The Mutations

+
Insert

Record New

Create a new row. Like dropping a sample into the sequencer.

await supabase

.from("todos")

.insert({

title: "New Task",

is_complete: false

})

~
Update

Remix Existing

Modify a row. Adjusting the pitch on an existing note.

await supabase

.from("todos")

.update({

is_complete: true

})

.eq("id", todoId)

x
Delete

Erase Take

Remove a row. Deleting that bad vocal take forever.

await supabase

.from("todos")

.delete()

.eq("id", todoId)

Pro tip: Always use .eq() to target specific rows. Without it, you'll affect every row in the table.

Common Patterns

Signal Interference

"I'll learn SQL first"

No. Describe what you want in English. AI writes the SQL.

"I'll set up RLS later"

Dangerous. Enable RLS immediately. One exposed endpoint can leak everything.

"I need complex migrations"

For MVP? Just use the dashboard. Run raw SQL. Keep it simple.

"I need to optimize queries"

With 10 users? No. Make it work first. Optimize when you hit 10,000.

Clean Patch

Prompt-first development

"Create a hook that fetches todos for the current user" — let AI handle syntax.

Enable RLS immediately

Toggle it on in Supabase dashboard. Add policies as you go.

One table at a time

Start with one table. Get CRUD working. Add more when needed.

Console.log the response

Always log data and error to see what Supabase returns.

The Exercises

Synthesize the connection.

01

The Patch

Setup Supabase

  • Create Supabase Project
  • Copy Env Variables (URL, Key)
  • Prompt AI: "Setup Supabase client in Next.js 15"
Goal: Connect the wires
02

The Sequence

Create Table

  • Go to Supabase SQL Editor
  • Ask AI: "Write SQL for a 'todos' table with title, is_complete, and user_id"
  • Run the SQL
Goal: Create the container
03

The Signal

Fetch Data

  • Insert 1 row manually in Supabase
  • Prompt AI: "Create useTodos hook"
  • Display the data in your UI
Goal: See real data on screen

📋 The Prompt Template

Copy-paste this when asking AI for database work:

I am using the Next.js App Router with Supabase.
My Supabase client is at @/utils/supabase/client.ts.
Please create a hook called [HookName] that fetches from the [TableName] table.
Handle loading and error states.
Return the data typed properly.