# Why Integrate Claude with Supabase?
In today's fast-paced apps, static database queries fall short. Users expect personalized, real-time experiences—like product recommendations that adapt instantly to inventory changes or user behavior. Supabase, the open-source Firebase alternative, excels at real-time data with PostgreSQL, Realtime subscriptions, and Edge Functions. Pair it with Claude's superior reasoning via the Anthropic API, and you get AI-driven workflows that query, analyze, and act on live data.
This tutorial walks you through connecting Claude to Supabase for:
- Natural language to SQL generation for dynamic querying
- Real-time subscriptions triggering AI processing
- Personalized recommendations stored back in your DB
Perfect for e-commerce, dashboards, or any app needing smart, live insights.
## Prerequisites
Before diving in, ensure you have:
- A free [Supabase account](https://supabase.com) and new project
- [Anthropic API key](https://console.anthropic.com) (Claude Pro or API credits recommended)
- Node.js 18+ installed
- Basic familiarity with JavaScript/TypeScript and async/await
We'll use:
- `@supabase/supabase-js` for DB interactions
- `@anthropic-ai/sdk` for Claude API calls
## Step 1: Set Up Your Supabase Project
1. Log into Supabase Dashboard > Create a new project (e.g., "claude-supabase-demo").
2. Note your project's URL and anon key from Settings > API.
Create tables for an e-commerce demo:
```sql
-- Users table
CREATE TABLE users (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
preferences JSONB DEFAULT '{}',
created_at TIMESTAMP DEFAULT NOW()
);
-- Products table (with realtime)
CREATE TABLE products (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name TEXT NOT NULL,
category TEXT,
price DECIMAL(10,2),
stock INTEGER DEFAULT 0,
updated_at TIMESTAMP DEFAULT NOW()
);
-- User purchases
CREATE TABLE purchases (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES users(id),
product_id UUID REFERENCES products(id),
quantity INTEGER,
purchased_at TIMESTAMP DEFAULT NOW()
);
-- Enable RLS (optional for demo)
ALTER TABLE products ENABLE ROW LEVEL SECURITY;
ALTER TABLE purchases ENABLE ROW LEVEL SECURITY;
```
Run this in SQL Editor. Insert sample data:
```sql
INSERT INTO products (name, category, price, stock) VALUES
('Wireless Headphones', 'Electronics', 99.99, 50),
('Running Shoes', 'Apparel', 129.99, 30),
('Coffee Maker', 'Home', 79.99, 20);
INSERT INTO users (email, preferences) VALUES
('user@example.com', '{"categories": ["Electronics", "Home"]}');
INSERT INTO purchases (user_id, product_id, quantity) VALUES
((SELECT id FROM users LIMIT 1), (SELECT id FROM products WHERE name='Wireless Headphones' LIMIT 1), 1);
```
Enable Realtime on `products` and `purchases` tables via Dashboard > Realtime.
## Step 2: Initialize Your Node.js Project with Claude SDK
Create a new directory:
```bash
mkdir claude-supabase-demo
cd claude-supabase-demo
npm init -y
npm install @supabase/supabase-js @anthropic-ai/sdk dotenv
npm install -D typescript @types/node ts-node
```
Create `.env`:
```env
SUPABASE_URL=your_supabase_url
SUPABASE_ANON_KEY=your_supabase_anon_key
ANTHROPIC_API_KEY=your_anthropic_key
```
`supabase.ts`:
```typescript
import { createClient } from '@supabase/supabase-js';
import dotenv from 'dotenv';
dotenv.config();
export const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_ANON_KEY!
);
```
`anthropic.ts`:
```typescript
import Anthropic from '@anthropic-ai/sdk';
import dotenv from 'dotenv';
dotenv.config();
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
export default anthropic;
```
## Step 3: Dynamic Data Querying with Claude (Text-to-SQL)
Claude excels at generating precise SQL. Let's query user purchase history naturally.
`queryData.ts`:
```typescript
import { supabase } from './supabase';
import anthropic from './anthropic';
async function nlToSQLQuery(nlQuery: string, userId: string) {
const prompt = `Generate a PostgreSQL SELECT query for Supabase based on this natural language: "${nlQuery}"
User ID: ${userId}
Relevant tables: users, products, purchases.
Use JOINs. Return ONLY the SQL query, no explanations.`;
const { content } = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20240620',
max_tokens: 1000,
messages: [{ role: 'user', content: prompt }],
});
const sql = content[0].text.trim();
console.log('Generated SQL:', sql);
const { data, error } = await supabase.rpc('execute_query', { query_text: sql });
// Note: For security, use Edge Functions or validate SQL in prod
if (error) throw error;
return data;
}
// Usage
nlToSQLQuery("Show my recent electronics purchases", "user-uuid-here");
```
**Security Note:** In production, validate generated SQL or use Supabase Edge Functions with `pg_vector` for RAG-like querying. Claude's reasoning minimizes injection risks, but always sanitize.
## Step 4: Real-Time Subscriptions + AI Processing
Subscribe to `products` changes. When stock updates, trigger Claude for affected users' recs.
First, create a recs table:
```sql
CREATE TABLE recommendations (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES users(id),
recs JSONB,
generated_at TIMESTAMP DEFAULT NOW()
);
```
`realtimeAI.ts`:
```typescript
import { supabase } from './supabase';
import anthropic from './anthropic';
// Get user prefs and purchases for recs
graphql
async function generateRecsForUser(userId: string) {
const { data: purchases } = await supabase
.from('purchases')
.select('products(name, category, price)')
.eq('user_id', userId);
const { data: prefs } = await supabase
.from('users')
.select('preferences')
.eq('id', userId).single();
const prompt = `Generate 3 personalized product recommendations as JSON array [{name, reason}].
Past purchases: ${JSON.stringify(purchases)}
Preferences: ${JSON.stringify(prefs?.preferences)}
Current products: [list from DB].
Focus on available stock >0.`;
const { content } = await anthropic.messages.create({
model: 'claude-3-haiku-20240307', // Fast for realtime
max_tokens: 500,
messages: [{ role: 'user', content: prompt }],
});
const recs = JSON.parse(content[0].text);
await supabase.from('recommendations').upsert({ user_id: userId, recs });
}
// Realtime subscription
const channel = supabase.channel('products-changes')
.on(
'postgres_changes',
{
event: '*',
schema: 'public',
table: 'products',
},
async (payload) => {
console.log('Change:', payload);
// Find affected users (e.g., those who bought similar categories)
const { data: users } = await supabase
.from('users')
.select('id')
.contains('preferences.categories', [payload.new.category]);
for (const user of users || []) {
await generateRecsForUser(user.id);
}
}
)
.subscribe();
console.log('Listening for realtime changes...');
```
Run with `npx ts-node realtimeAI.ts`. Update a product's stock via Dashboard—watch Claude generate fresh recs!
## Step 5: Building Personalized Recommendations App
Combine everything into a full workflow. Fetch live recs in your frontend:
```typescript
// Frontend (e.g., Next.js)
const { data: recs } = await supabase
.from('recommendations')
.select('*')
.eq('user_id', userId)
.order('generated_at', { ascending: false })
.limit(1);
```
Display: "Claude recommends: ${recs[0].recs.map(r => r.name).join(', ')}"
## Step 6: Production Best Practices
- **Serverless:** Deploy to Supabase Edge Functions or Vercel. Trigger Claude via HTTP on DB events.
```typescript
// Edge Function example (Deno)
// denoland/supabase-edge-runtime
Deno.serve(async (req) => {
// Claude call + DB upsert
});
```
- **Rate Limits:** Claude API: 50 RPM for Sonnet. Use Haiku for high-volume realtime. Implement queues (BullMQ).
- **Costs:** Monitor token usage. Cache recs with TTL.
- **Error Handling:** Retry logic with exponential backoff.
- **Auth:** Use Supabase Auth + RLS for secure access.
- **Scaling:** Vectorize products with `pgvector` + Claude for semantic search.
## Advanced: AI Agents with MCP
Extend with [Claude Code CLI](https://docs.anthropic.com) or MCP servers for agentic workflows—e.g., Claude autonomously manages inventory based on sales trends.
## Conclusion
You've now built real-time AI database workflows: NL queries, live subs triggering Claude insights, and persistent recs. This powers dynamic apps like personalized dashboards or e-com upsells. Experiment with your data—Claude's context window handles complex schemas effortlessly.
Fork the [GitHub repo](https://github.com/example/claude-supabase-demo) (imagine it exists) and share your builds in comments!
*Word count: ~1450*