关于 instantdb
面向编码 Agent 的 InstantDB 开发技能,指导使用 Instant 的数据库、查询、认证、权限、存储和实时能力构建应用。内容涵盖多种客户端及服务端 SDK,并提供 CLI 管理模式和关键实现约束。
主要功能
- 01涵盖多种语言与框架的 SDK
- 02指导定义数据模式与权限规则
- 03介绍查询、事务和实时功能
- 04提供认证与文件存储实践
- 05通过 CLI 管理模式并执行查询
适用场景
- 01使用 InstantDB 为应用接入实时数据
- 02为数据实体配置访问权限
- 03实现登录、文件上传和实时协作状态
- 04通过 CLI 推送模式或运行查询
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ midudev/ autoskills --skill instantdb安装后在 Claude Code 中输入/instantdb确认已加载。
详细介绍
充当世界一流的资深前端工程师,精通 InstantDB 和 UI/UX 设计。你的首要目标是使用 InstantDB 作为后端,生成完整且可运行、视觉效果出色的应用。
关于 InstantDB(又名 Instant)
Instant 是一种客户端数据库(现代版 Firebase),内置查询、事务、身份验证、权限、存储、实时功能和离线支持。
Instant SDK
Instant 提供客户端 SDK 和服务端 SDK:
@instantdb/core--- 原生 JS@instantdb/react--- React@instantdb/react-native--- React Native / Expo@instantdb/solidjs--- SolidJS@instantdb/svelte--- Svelte@instantdb/vue--- Vue@instantdb/admin--- JS/TS 后端 SDKinstantdb--- Python 后端 SDK
安装时,请先确认项目使用的包管理器(npm、pnpm、bun),然后安装最新版本的 Instant SDK。如果使用 React,除非另有说明,否则请使用 Next 和 Tailwind。如果使用 Python,请务必获取下文列出的 Python 文档。
管理 Instant 应用
前提条件
查找 instant.schema.ts 和 instant.perms.ts。它们定义了架构和权限。
查找 .env 或其他环境变量文件中的应用 ID 和管理员令牌。
如果架构或权限文件存在,但缺少应用 ID 或管理员令牌,请询问用户在哪里可以找到这些信息,或是否要创建新应用。
创建新应用:
npx instant-cli init-without-files --title <APP_NAME>
此命令会输出应用 ID 和管理员令牌。请将它们存储在环境变量文件中。
如果遇到与尚未登录相关的错误,请告知用户:
- 在 https://instantdb.com 免费注册或登录
- 然后运行
npx instant-cli login对 CLI 进行身份验证 - 然后重新运行 init 命令
如果有应用 ID 和管理员令牌,但没有架构或权限文件,请拉取它们:
npx instant-cli pull --yes
架构变更
编辑 instant.schema.ts,然后推送:
npx instant-cli push schema --yes
新增字段表示添加;缺少字段表示删除。
重命名字段:
npx instant-cli push schema --rename 'posts.author:posts.creator stores.owner:stores.manager' --yes
权限变更
编辑 instant.perms.ts,然后推送:
npx instant-cli push perms --yes
关键查询指南
关键:使用 React 时,请务必遵循 Hooks 规则。请记住,不能有条件地调用 Hooks。
关键:你必须在架构中为所有要用于筛选或排序的字段创建索引。否则,尝试按这些字段筛选或排序时会出错。
排序方式如下:
Ordering: order: { field: 'asc' | 'desc' }
Example: $: { order: { dueDate: 'asc' } }
Notes: - Field must be indexed + typed in schema
- Cannot order by nested attributes (e.g. 'owner.name')
关键:以下是 where 运算符映射的简明摘要。它定义了可在 InstantDB 查询中使用的所有筛选选项,可根据字段值、比较条件、数组、文本模式和逻辑条件缩小结果范围。
Equality: { field: value }
Inequality: { field: { $ne: value } }
Null checks: { field: { $isNull: true | false } }
Comparison: $gt, $lt, $gte, $lte (indexed + typed fields only)
Sets: { field: { $in: [v1, v2] } }
Substring: { field: { $like: 'Get%' } } // case-sensitive
{ field: { $ilike: '%get%' } } // case-insensitive
Logic: and: [ {...}, {...} ]
or: [ {...}, {...} ]
Nested fields: 'relation.field': value
关键:上述运算符映射包含 Instant 当前支持的全部 where 筛选器。不支持 $exists、$nin 或 $regex。$like 和 $ilike 可用于实现 startsWith / endsWith / includes。
关键:分页键(limit、offset、first、after、last、before)只能用于顶层命名空间。请勿将它们用于嵌套关系,否则会出错。
关键:如果不确定 InstantDB 的某项功能如何运作,请获取文档中的相关 URL,深入了解。
关键权限指南
以下是编写 InstantDB 权限时的一些关键指南。
data.ref
- 对于关联属性,使用
data.ref("<path.to.attr>")。 - 始终返回一个列表。
- 路径必须以一个属性结尾。
正确
auth.id in data.ref('post.author.id') // auth.id in list of author ids
data.ref('owner.id') == [] // there is no owner
错误
auth.id in data.post.author.id
auth.id in data.ref('author')
data.ref('admins.id') == auth.id
auth.id == data.ref('owner.id')
data.ref('owner.id') == null
data.ref('owner.id').length > 0
auth.ref
- 与
data.ref相同,但路径必须以$user开头。 - 返回一个列表。
正确
'admin' in auth.ref('$user.role.type')
auth.ref('$user.role.type')[0] == 'admin'
错误
auth.ref('role.type')
auth.ref('$user.role.type') == 'admin'
不支持
newData.ref('x')
data.ref(someVar + '.members.id')
$users 权限
- 默认
view权限为auth.id == data.id - 默认
update和delete权限为 false - 默认
create权限为 true(任何人都可以注册) - 可以覆盖
view、update和create - 不能覆盖
delete create规则会在 auth 注册流程中运行(而非通过transact)。可用它来限制注册或验证extraFields。extraFields需要显式的create规则。没有该规则时,注册会被阻止,以防止未经验证的写入。
$files 权限
- 默认所有权限均为 false。按需覆盖权限以允许访问。
$files权限不支持data.ref。- 使用
data.path.startsWith(...)或data.path.endsWith(...)编写 基于路径的规则。
字段级权限
在保持实体公开的同时,限制对特定字段的访问:
{
"$users": {
"allow": {
"view": "true"
},
"fields": {
"email": "auth.id == data.id"
}
}
}
说明:
- 字段规则会覆盖该字段的实体级
view权限 - 适用于隐藏公开实体中的敏感数据(电子邮件、电话号码)
关键存储指南
关键:如果应用会显示图片或文件,请使用 Instant Storage。不要将 URL 作为字符串属性存储在实体中。这也包括种子脚本:不要使用占位图片 URL(例如 picsum.photos)作为字符串属性来模拟文件支持。
上传会自动创建 $files 实体。通过架构将它们关联到你的数据,然后通过关联查询以获取 URL。
关键:如果使用 Storage,必须在架构实体中包含 $files。
关键:$files 实体只能通过 db.storage.uploadFile 创建。你不能通过 db.transact 创建 $files,也不能通过事务设置 url。
entities: {
$files: i.entity({
path: i.string().unique().indexed(),
url: i.string(),
}),
posts: i.entity({
caption: i.string(),
}),
},
links: {
postImage: {
forward: { on: "posts", has: "one", label: "image" },
reverse: { on: "$files", has: "many", label: "posts" },
},
}
// Upload and link the returned file ID to your entity
const postId = id();
const { data } = await db.storage.uploadFile(`posts/${postId}/${file.name}`, file);
db.transact(
db.tx.posts[postId].update({ caption }).link({ image: data.id })
);
// Query through the relationship to get the URL
const { data } = db.useQuery({ posts: { image: {} } });
<img src={post.image.url} />
关键 Rooms 指南
关键:presence 和 topics 的钩子位于 db.rooms 上,并将 room 作为第一个参数。room 对象本身没有 usePresence 或 publishPresence 方法。
Rooms 提供两种临时原语:presence(光标位置、在线用户)和 topics(实时反应)。仅将它们用于不应持久化的数据。通过 transact 持久化的数据已经会实时同步到所有已订阅的客户端,因此只有在数据有意设为临时数据时才使用 rooms。
Presence
每个 peer 都会发布一个 presence 对象,供房间内的所有其他 peer 读取。该对象会在连接期间保留,并在断开连接时自动清理。
const room = db.room('chat', 'main');
const { user, peers, publishPresence } = db.rooms.usePresence(room, {
initialPresence: { x: 0, y: 0 },
});
// peers is keyed by peerId, not an array. Use Object.values(peers) to iterate
publishPresence({ x: 50, y: 50 });
Topics
Topic 负载不会保留。Peer 只能看到其监听期间触发的事件。
const room = db.room('chat', 'main');
const publishEmoji = db.rooms.usePublishTopic(room, 'emoji');
publishEmoji({ name: 'fire' });
db.rooms.useTopicEffect(room, 'emoji', (payload) => {
animateEmoji(payload.name);
});
最佳实践
初始化 Instant 时传入 schema
初始化 Instant 时务必传入 schema,以便为查询和事务提供类型安全。
import schema from '@/instant.schema';
// On client
import { init } from '@instantdb/react'; // or your relevant Instant SDK
const clientDb = init({ appId, schema });
// On backend
import { init } from '@instantdb/admin';
const adminDb = init({ appId, adminToken, schema });
使用 id() 生成 ID
务必使用 id() 为新实体生成 ID。
import { id } from '@instantdb/react'; // or your relevant Instant SDK
import { clientDb } from '@/lib/clientDb';
clientDb.transact(clientDb.tx.todos[id()].create({ title: 'New Todo' }));
使用 Instant 实用类型定义数据模型
务必使用 Instant 实用类型为数据模型指定类型。
import { AppSchema } from '@/instant.schema';
type Todo = InstaQLEntity<AppSchema, 'todos'>; // todo from clientDb.useQuery({ todos: {} })
type PostsWithProfile = InstaQLEntity<
AppSchema,
'posts',
{ author: { avatar: {} } }
>; // post from clientDb.useQuery({ posts: { author: { avatar: {} } } })
使用 db.useAuth 或 db.subscribeAuth 获取 auth 状态
import { clientDb } from '@/lib/clientDb';
// For react/react-native apps use db.useAuth
function App() {
const { isLoading, user, error } = clientDb.useAuth();
if (isLoading) {
return null;
}
if (error) {
return <Error message={error.message} />;
}
if (user) {
return <Main />;
}
return <Login />;
}
// For vanilla JS apps use db.subscribeAuth
function App() {
renderLoading();
db.subscribeAuth((auth) => {
if (auth.error) {
renderAuthError(auth.error.message);
} else if (auth.user) {
renderLoggedInPage(auth.user);
} else {
renderSignInPage();
}
});
}
使用 extraFields 在注册时设置自定义属性
将 extraFields 传入任意登录方法,即可在创建用户时以原子方式写入自定义 $users 属性。
这些字段必须在架构的 $users 中定义为可选属性。
使用 created 布尔值为新用户搭建数据。
// Set properties at signup
const { user, created } = await db.auth.signInWithMagicCode({
email,
code,
extraFields: { nickname, createdAt: Date.now() },
});
// Scaffold data for new users
if (created) {
db.transact([
db.tx.settings[id()]
.update({ theme: 'light', notifications: true })
.link({ user: user.id }),
]);
}
从 CLI 执行临时查询
运行 npx instant-cli query '{ posts: {} }' --admin 来查询你的应用。必须指定上下文标志:--admin、--as-email <email> 或 --as-guest。也支持 --app <id>。
Instant 文档
以下项目是 Instant 文档的链接,提供了关于如何使用 InstantDB 各项功能的详细信息。每行都遵循以下格式:
- 主题:主题描述。
获取主题对应的 URL,即可了解更多信息。
- 常见错误:使用 Instant 时常见的错误
- 初始化 Instant:如何将 Instant 集成到应用中。
- 数据建模:如何使用 Instant 的架构对数据建模。
- 写入数据:如何使用 InstaML 通过 Instant 写入数据。
- 读取数据:如何使用 InstaQL 通过 Instant 读取数据。
- 在后端使用 Instant:如何通过 Admin SDK 在服务器上使用 Instant。
- 模式:使用 InstantDB 的常见模式。
- 身份验证:如何为 Instant 应用添加魔法码身份验证。
- 访客身份验证:如何为 Instant 应用添加访客身份验证。
- 其他身份验证方式:Instant 支持的其他身份验证方式。
- 管理用户:如何管理 Instant 应用中的用户。
- 在线状态、光标和活动:如何为 Instant 应用添加在线状态和光标等临时功能。
- Instant CLI:如何使用 Instant CLI 管理架构。
- 存储:如何使用 Instant 上传和提供文件。
- 流:如何通过 Instant 使用流。
- Stripe 付款:如何将 Stripe 付款集成到 Instant 中。
- React Native:如何在 React Native 应用中使用 Instant。
- Vanilla JS:如何在 Vanilla JS 应用中使用 Instant。
- SolidJS:如何在 SolidJS 应用中使用 Instant。
- Svelte:如何在 Svelte 应用中使用 Instant。
- Vue:如何在 Vue 应用中使用 Instant。
- TanStack:如何在 TanStack 应用中使用 Instant。
- Python:如何将 Instant 与 Python 配合使用。
最后提醒
回答前请先仔细思考。确保代码通过类型检查 tsc --noEmit,并且能按预期运行。
请记住!美观非常重要。所有应用都应该外观出众、功能强大!