一键导入
supabase-artifact-connection
Connect Supabase databases to Claude Desktop artifacts with read-only queries and live data visualization.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Connect Supabase databases to Claude Desktop artifacts with read-only queries and live data visualization.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Execute tasks efficiently with minimal explanations. Deliver results first, explanations only when needed. Optimized for action-focused workflows and ADHD-friendly responses.
Apply the complete CURV Tools design system to all visual outputs - dashboards, reports, HTML artifacts, and data visualizations. Includes exact colors from production tools (rgb(3, 12, 27) dark background, rgb(157, 78, 221) purple accent), glassmorphic effects, gradient borders, header/footer templates, and animation patterns used in GL Decoder and SQPR Analyser.
Automatically convert uploaded data (CSV, Excel, JSON) into complete interactive dashboards with zero user input required. Detects patterns in PPC reports, sales data, analytics exports, and business metrics - then generates insights, recommendations, and visualizations instantly. Works seamlessly with CURV design system for on-brand outputs with tabs, funnels, filters, and multi-view layouts.
Generate professional slide decks and presentations using Formula Botanica brand guidelines - green botanical theme with Roboto Light/Thin fonts, leaf logo motifs, and clean layouts for finance processes, team presentations, and internal documentation.
Connect Supabase databases to Claude Desktop artifacts with authentication and read-only queries using native fetch API.
基于 SOC 职业分类
| name | supabase-artifact-connection |
| description | Connect Supabase databases to Claude Desktop artifacts with read-only queries and live data visualization. |
Enable live database connections in artifacts using Supabase client library with enforced read-only access.
This skill activates when:
User must provide:
SUPABASE_URL = 'https://[project-id].supabase.co'
SUPABASE_ANON_KEY = 'eyJhbGc...' // Public anon key
Always use this exact pattern in artifacts:
<!-- Supabase Client Library -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script>
// Initialize Supabase client
const SUPABASE_URL = 'USER_PROVIDED_URL';
const SUPABASE_ANON_KEY = 'USER_PROVIDED_KEY';
const supabase = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
// Query example
async function loadData() {
const { data, error } = await supabase
.from('table_name')
.select('*')
.limit(100);
if (error) {
console.error('Supabase query error:', error);
return null;
}
return data;
}
</script>
CRITICAL: NEVER generate code that writes to Supabase.
.select() - Query data.from() - Specify table.eq(), .gt(), .lt(), .in(), .not(), .like(), .ilike().order().limit(), .range().count(), .sum(), .avg(), .min(), .max().insert() - Create records.update() - Modify records.upsert() - Insert or update.delete() - Remove recordsIf user requests write operations, respond:
"This skill only supports read-only queries to protect database integrity. For write operations, use Supabase Dashboard or a dedicated backend service."
const { data, error } = await supabase
.from('products')
.select('*');
const { data, error } = await supabase
.from('products')
.select('name, price, category')
.eq('category', 'Electronics')
.gt('price', 100)
.order('price', { ascending: false })
.limit(50);
const { count, error } = await supabase
.from('products')
.select('*', { count: 'exact', head: true });
const { data, error } = await supabase
.from('orders')
.select(`
id,
created_at,
customer:customers(name, email),
items:order_items(product_name, quantity)
`)
.limit(20);
Generate artifacts with this structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Supabase Data Viewer</title>
<!-- Supabase Client -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.loading {
text-align: center;
padding: 40px;
color: #666;
}
.error {
background: #fee;
border: 1px solid #fcc;
padding: 15px;
border-radius: 4px;
color: #c33;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
th, td {
text-align: left;
padding: 12px;
border-bottom: 1px solid #ddd;
}
th {
background: #f8f8f8;
font-weight: 600;
}
</style>
</head>
<body>
<div class="container">
<h1>Supabase Data</h1>
<div id="content">
<div class="loading">Loading data...</div>
</div>
</div>
<script>
// Initialize Supabase
const SUPABASE_URL = 'USER_PROVIDED_URL';
const SUPABASE_ANON_KEY = 'USER_PROVIDED_KEY';
const supabase = window.supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
// Load and display data
async function loadData() {
const contentDiv = document.getElementById('content');
try {
const { data, error } = await supabase
.from('table_name')
.select('*')
.limit(100);
if (error) throw error;
if (data.length === 0) {
contentDiv.innerHTML = '<p>No data found.</p>';
return;
}
// Create table
const columns = Object.keys(data[0]);
let html = '<table><thead><tr>';
columns.forEach(col => html += `<th>${col}</th>`);
html += '</tr></thead><tbody>';
data.forEach(row => {
html += '<tr>';
columns.forEach(col => html += `<td>${row[col] ?? ''}</td>`);
html += '</tr>';
});
html += '</tbody></table>';
contentDiv.innerHTML = html;
} catch (error) {
contentDiv.innerHTML = `<div class="error">Error loading data: ${error.message}</div>`;
}
}
// Load on page load
loadData();
</script>
</body>
</html>
Always include error handling:
try {
const { data, error } = await supabase
.from('table_name')
.select('*');
if (error) throw error;
// Process data
console.log('Data loaded:', data);
} catch (error) {
console.error('Supabase error:', error);
// Show user-friendly error message
alert('Failed to load data. Check console for details.');
}
Error: "Invalid API key"
eyJhbGc...Error: "Table not found"
Error: "Row Level Security policy violation"
Error: "CORS error"
Limit results: Always use .limit() for large tables
.limit(100) // Don't fetch more than needed
Select specific columns: Avoid SELECT * when possible
.select('id, name, created_at') // Only fetch needed columns
Use filters: Apply filters server-side, not client-side
.eq('status', 'active') // Filter in query, not in JavaScript
Cache data: Store results in variables to avoid re-querying
let cachedData = null;
async function getData() {
if (cachedData) return cachedData;
const { data } = await supabase.from('table').select('*');
cachedData = data;
return data;
}
Before sharing artifact with user:
Artifact is successful when:
Simple Data Table:
// Load and display all records
const { data } = await supabase.from('customers').select('*').limit(50);
Filtered Dashboard:
// Show active users only
const { data } = await supabase
.from('users')
.select('name, email, created_at')
.eq('status', 'active')
.order('created_at', { ascending: false });
Search Interface:
// Search by name (case-insensitive)
const { data } = await supabase
.from('products')
.select('*')
.ilike('name', `%${searchTerm}%`);
Analytics View:
// Get aggregated data
const { count } = await supabase
.from('orders')
.select('*', { count: 'exact', head: true })
.gte('created_at', '2025-01-01');
Once basic connection works:
Remember: Always start with basic connection, then enhance incrementally based on user needs.