> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/ai-vibe-coding/zh/integration/ji-cheng-supabase.md).

# 集成 Supabase

介绍在 Apps in Toss（迷你应用）WebView 环境中集成 Supabase 的方法。Supabase JS 客户端可独立于框架运行。代码示例基于 **Vite(React + TypeScript)** 编写而成。

***

### 概要

Supabase 是提供认证、数据库（PostgreSQL）、文件存储、实时订阅等功能的开源后端服务。在 Apps in Toss WebView 环境中也可以同样使用，但 **安全设置与环境变量管理**很重要。

***

### 1. 准备

* Supabase 账户（[supabase.com](https://supabase.com))
* 使用 Vite(React + TypeScript) 创建的项目
* Node.js、npm（或 yarn、pnpm）

### 2. 创建 Supabase 项目

1. 在 Supabase 仪表板中 **New project**即可创建新项目。
2. 设置项目名称、数据库密码和区域后完成创建。
3. 项目准备就绪后，可在仪表板中查看以下信息。

```
Project URL     : https://<project-id>.supabase.co
Publishable key : sb_publishable_xxxxxxxxxxxx
```

### 3. 设置环境变量

建议将 Supabase 连接信息作为环境变量管理以确保安全。在项目根目录中 `.env` 创建文件并按如下方式填写。

```bash
VITE_SUPABASE_URL=https://<project-id>.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_xxxxxxxxxxxx
```

### 4. 安装并初始化 Supabase

`src/supabase/client.ts` 创建文件并按如下方式初始化 Supabase 客户端。

```bash
npm install @supabase/supabase-js
```

```ts
import { createClient } from '@supabase/supabase-js';

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabasePublishableKey = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY;

export const supabase = createClient(supabaseUrl, supabasePublishableKey);
```

{% hint style="info" %}
**参考**

Publishable key 就像 Stripe 的 `pk_live_...`，Firebase 的 `apiKey`这类可以暴露给客户端的公开密钥。不过， **必须设置 RLS（Row Level Security）策略** 。没有 RLS 时，只要有 publishable key，任何人都可以读取和写入整张表。

`secret` 密钥是可完全绕过 RLS 的秘密密钥。仅在服务器端使用，绝不要暴露给客户端。
{% endhint %}

### 5. 数据库使用示例

如果已初始化 Supabase 客户端，就可以在 React 组件中读取或写入数据。下面是 `App.tsx`中读取并保存单行数据的最简单示例。

在 Supabase 仪表板的 **Table Editor**中 `users` 创建表， `id`（int8，primary key）和 `name`（text）列。

```tsx
import { useState, useEffect } from 'react';
import { supabase } from './supabase/client';

function App() {
  const [name, setName] = useState('');
  const [savedName, setSavedName] = useState('');

  // 从 Supabase 读取数据
  useEffect(() => {
    const fetchData = async () => {
      const { data } = await supabase.from('users').select('name').eq('id', 1).single();
      if (data) {
        setSavedName(data.name);
      }
    };
    fetchData();
  }, []);

  // 向 Supabase 写入数据
  const handleSave = async () => {
    await supabase.from('users').upsert({ id: 1, name });
    setSavedName(name);
    setName('');
  };

  return (
    <div style={{ padding: 24 }}>
      <h1>Supabase 简单示例</h1>
      <input value={name} onChange={(e) => setName(e.target.value)} placeholder="输入姓名" />
      <button onClick={handleSave}>保存</button>
      <p>已保存的姓名: {savedName || '(无)'}</p>

  );
}

export default App;
```

#### 工作方式

* 读取数据（`.select()`)
  * `users` 在表中 `id`只会获取 id 为 1 的行一次。
  * 如果存在该行 `name` 将值显示在屏幕上。
* 写入数据（`.upsert()`)
  * 将输入的姓名 `users` 保存到表中。
  * 如果没有该行则新建，有则覆盖。

{% hint style="info" %}
**Supabase 其他功能**

* 实时订阅： `.channel()`, `.on()`使用它们时，数据变更后 UI 会自动刷新。
* 文件存储： `supabase.storage`可以上传图片或文件。
* 认证集成： `supabase.auth`配合使用后可以按用户保存数据。
  {% endhint %}

### 6. 安全检查清单

* 通过环境变量管理敏感信息
  * Supabase URL、publishable key 等不要直接写入代码， `.env`请用环境变量管理。
* 不要将环境文件上传到 Git 等平台
  * `.env` 文件 `.gitignore`中一定要添加。
  * 如果密钥泄露，请立即在 Supabase 仪表板重新签发密钥。
* **必须设置 Row Level Security(RLS)**
  * Supabase 的所有表默认都未启用 RLS。
  * 在关闭 RLS 的情况下，只要有 publishable key，任何人都能访问整张表。
  * 部署前务必启用 RLS，并设置策略（Policy）以仅允许已认证用户访问。
  * Supabase 仪表板 **Table Editor → 选择表 → RLS** 可在选项卡中进行设置。
* 检查来源（Origin）限制
  * 在 Supabase 仪表板的 **Authentication → URL Configuration**中限制允许的域名。
  * 只允许迷你应用（WebView）域名可预防未授权访问。

{% hint style="info" %}
**允许的域名**

因 SDK 版本而异。\n\nSDK 3.x\
`https://<appName>.web.tossmini.com` — 实际服务环境 \
`https://<appName>.private-web.tossmini.com` — 控制台 QR 测试环境\n\nSDK 1.x \~ 2.x\
`https://<appName>.apps.tossmini.com` — 实际服务环境 \
`https://<appName>.private-apps.tossmini.com` — 控制台 QR 测试环境
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/ai-vibe-coding/zh/integration/ji-cheng-supabase.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
