integrating-convex-expo
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseIntegrating Convex with Expo (React Native)
将Convex与Expo(React Native)整合
Use this skill to add, repair, extend, or harden a Convex backend for an Expo app without drifting into web-only patterns or generic React Native advice.
使用本技能可为Expo应用添加、修复、扩展或强化Convex后端,同时避免陷入仅适用于Web的模式或通用React Native建议。
Use this skill for
适用场景
- Adding Convex to an existing Expo or Expo Router app.
- Fixing broken environment setup, provider wiring, or generated API imports.
- Building an end-to-end feature slice: schema, indexes, backend functions, frontend hooks, and validation.
- Choosing and implementing auth for Expo + Convex.
- Uploading files from Expo URIs into Convex storage.
- Refactoring for pagination, indexes, migrations, or reusable components.
- Hardening a project before preview or production release.
- 为现有Expo或Expo Router应用添加Convex。
- 修复损坏的环境配置、提供者连接或生成的API导入问题。
- 构建端到端功能切片:Schema、索引、后端函数、前端钩子及验证逻辑。
- 为Expo + Convex选择并实现认证方案。
- 将文件从Expo URIs上传至Convex存储。
- 针对分页、索引、迁移或可复用组件进行重构。
- 在预览或生产发布前强化项目稳定性。
Do not use this skill for
不适用场景
- Pure Expo UI, animation, navigation, or styling work with no Convex involvement.
- Convex projects whose frontend is not Expo or React Native.
- Generic backend architecture discussions that do not need Expo-specific environment or client wiring.
- 无Convex参与的纯Expo UI、动画、导航或样式开发。
- 前端非Expo或React Native的Convex项目。
- 无需Expo特定环境或客户端配置的通用后端架构讨论。
Success criteria
成功标准
A good outcome should leave the project with:
- A single, correctly scoped Convex client and provider.
- Working handling in local development and EAS.
EXPO_PUBLIC_CONVEX_URL - Backend functions that match Convex best practices for validators, auth, actions, and query performance.
- Frontend hooks using generated references with clear loading, empty, and error states.
api - A validation pass using .
scripts/validate_project.py - A clear path for future growth: pagination, indexes, auth wrappers, migrations, and linting.
理想的处理结果应满足以下要求:
- 单个范围正确的Convex客户端与提供者。
- 在本地开发和EAS中正确处理。
EXPO_PUBLIC_CONVEX_URL - 后端函数符合Convex最佳实践,包含验证器、认证、动作及查询性能优化。
- 前端钩子使用生成的引用,并清晰处理加载、空值及错误状态。
api - 通过完成验证检查。
scripts/validate_project.py - 具备清晰的未来扩展路径:分页、索引、认证封装、迁移及代码检查。
Non-negotiables
必须遵守规则
- Keep running while developing or repairing the integration.
npx convex dev - Read the deployment URL from .
process.env.EXPO_PUBLIC_CONVEX_URL - Mirror that value into EAS environments for preview and production builds.
- Create exactly one per app, outside render paths.
ConvexReactClient - Mount the provider at the true root: ,
app/_layout.tsx, orsrc/app/_layout.tsx.App.tsx - In Expo and React Native, set .
unsavedChangesWarning: false - Import generated references from rather than stringly typed names.
convex/_generated/api - Treat all client-callable Convex functions as untrusted entry points.
- Add validators to public functions, and prefer
argsvalidators as well.returns - Keep public wrappers thin; move repeated logic into helpers, internal functions, or custom wrappers.
- Do not use or
Date.now()inside query logic.new Date() - Do not use Node-only APIs or third-party SDKs inside queries or mutations.
- Put external API calls, heavy compute, or Node-only libraries in or
actionfiles; if a file starts withinternalAction, keep it action-only."use node" - Avoid and unbounded
.filter()on large tables; prefer indexes plus pagination..collect() - Await every promise.
- Prefer TypeScript strict mode and the official Convex ESLint plugin.
- 开发或修复整合过程中保持运行。
npx convex dev - 从读取部署URL。
process.env.EXPO_PUBLIC_CONVEX_URL - 将该值同步到预览和生产构建的EAS环境中。
- 每个应用仅创建一个,且置于渲染路径之外。
ConvexReactClient - 在真正的根节点挂载提供者:、
app/_layout.tsx或src/app/_layout.tsx。App.tsx - 在Expo和React Native中设置。
unsavedChangesWarning: false - 从导入生成的引用,而非手写函数名称。
convex/_generated/api - 将所有可被客户端调用的Convex函数视为不可信入口点。
- 为公共函数添加验证器,同时优先添加
args验证器。returns - 保持公共封装层简洁;将重复逻辑移至辅助函数、内部函数或自定义封装中。
- 请勿在查询逻辑中使用或
Date.now()。new Date() - 请勿在查询或变更中使用仅Node可用的API或第三方SDK。
- 将外部API调用、大量计算或仅Node可用的库置于或
action文件中;若文件以internalAction开头,仅用于动作逻辑。"use node" - 避免对大型表使用和无限制的
.filter();优先使用索引加分页。.collect() - 等待所有Promise完成。
- 优先使用TypeScript严格模式及官方Convex ESLint插件。
First-pass triage
初步诊断流程
Before making changes, inspect the project and classify the job.
进行修改前,先检查项目并分类任务。
1. Identify the app entrypoint
1. 识别应用入口点
Check for:
- or
app/_layout.tsxfor Expo Router.src/app/_layout.tsx - or
App.tsxfor classic entrypoints.App.jsx
检查以下文件:
- Expo Router项目的或
app/_layout.tsx。src/app/_layout.tsx - 传统项目的或
App.tsx。App.jsx
2. Audit Convex state
2. 审计Convex状态
Look for:
- dependencies:
package.json,convex, auth libraries, ESLint tooling.expo - and
convex/.convex/_generated/ - ,
.env.local,.env,.env.development..env.production - if cloud builds matter.
eas.json - Existing provider usage: ,
ConvexProvider, or custom auth wrappers.ConvexProviderWithClerk - Existing schema and indexes in .
convex/schema.ts - Existing public functions with missing validators, auth checks, or pagination.
查看以下内容:
- 依赖:
package.json、convex、认证库、ESLint工具。expo - 和
convex/目录。convex/_generated/ - 、
.env.local、.env、.env.development环境文件。.env.production - 涉及云构建的。
eas.json - 已有的提供者使用情况:、
ConvexProvider或自定义认证封装。ConvexProviderWithClerk - 中已有的Schema和索引。
convex/schema.ts - 缺少验证器、认证检查或分页逻辑的现有公共函数。
3. Run the validator
3. 运行验证脚本
From the project root:
bash
python scripts/validate_project.py --root <project-root>Use for machine-readable output or when you want stricter gating.
--json--fail-on-warning从项目根目录执行:
bash
python scripts/validate_project.py --root <project-root>使用参数获取机器可读输出,或使用参数启用更严格的检查。
--json--fail-on-warning4. Choose the workflow
4. 选择工作流
- Bootstrap / repair baseline: missing Convex setup, env vars, provider, or generated API.
- Build a feature slice: add backend data and UI together.
- Auth: add or repair sign-in and backend authorization.
- File uploads: move media or documents from device URIs into Convex storage.
- Scale / harden: indexes, pagination, components, linting, production checklist.
- Migration: reshape existing tables or gradually move from another backend.
- 初始化/修复基线整合:缺失Convex配置、环境变量、提供者或生成的API。
- 构建功能切片:同时添加后端数据与UI。
- 认证配置:添加或修复登录及后端授权逻辑。
- 文件上传:将媒体或文档从设备URIs迁移至Convex存储。
- 扩展/强化:索引、分页、组件、代码检查、生产发布清单。
- 迁移:重构现有表或逐步从其他后端迁移。
Workflow A — Bootstrap or repair the baseline integration
工作流A — 初始化或修复基线整合
Step 1: Install or confirm the client package
步骤1:安装或确认客户端包
bash
npx expo install convexbash
npx expo install convexStep 2: Create or reconnect the Convex project
步骤2:创建或重新连接Convex项目
bash
npx convex devExpect this to:
- create or connect a Convex project,
- create if missing,
convex/ - generate ,
convex/_generated/ - write to
EXPO_PUBLIC_CONVEX_URL,.env.local - and keep syncing while the command runs.
bash
npx convex dev预期执行结果:
- 创建或连接Convex项目,
- 若缺失则创建目录,
convex/ - 生成,
convex/_generated/ - 将写入
EXPO_PUBLIC_CONVEX_URL,.env.local - 运行期间保持同步。
Step 3: Ensure the root provider exists
步骤3:确保根提供者存在
For Expo Router:
tsx
import { ConvexProvider, ConvexReactClient } from "convex/react";
import { Stack } from "expo-router";
const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!, {
unsavedChangesWarning: false,
});
export default function RootLayout() {
return (
<ConvexProvider client={convex}>
<Stack />
</ConvexProvider>
);
}For classic , wrap the top-level navigation tree the same way.
App.tsxExpo Router项目示例:
tsx
import { ConvexProvider, ConvexReactClient } from "convex/react";
import { Stack } from "expo-router";
const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!, {
unsavedChangesWarning: false,
});
export default function RootLayout() {
return (
<ConvexProvider client={convex}>
<Stack />
</ConvexProvider>
);
}传统项目需以相同方式包裹顶层导航树。
App.tsxStep 4: Confirm generated imports
步骤4:确认生成的导入
Use:
ts
import { api } from "../convex/_generated/api";or the correct relative path for the project layout. Do not hand-write function names.
使用以下导入方式:
ts
import { api } from "../convex/_generated/api";或根据项目结构使用正确的相对路径。请勿手写函数名称。
Step 5: Verify development and build environments
步骤5:验证开发与构建环境
Read references/eas-env.md and ensure the same deployment URL policy is reflected in EAS.
阅读references/eas-env.md,确保EAS中配置了一致的部署URL策略。
Step 6: Validate and smoke-test
步骤6:验证与冒烟测试
- Start the Expo app.
- Confirm moves from
useQuery(...)to real data.undefined - Run .
python scripts/validate_project.py --root <project-root> - If needed, scaffold the canonical example with .
python scripts/scaffold_tasks_example.py --root <project-root>
- 启动Expo应用。
- 确认从
useQuery(...)变为真实数据。undefined - 执行。
python scripts/validate_project.py --root <project-root> - 若需要,使用搭建标准示例。
python scripts/scaffold_tasks_example.py --root <project-root>
Workflow B — Build a feature slice end to end
工作流B — 端到端构建功能切片
Build each feature in the order below.
按以下顺序构建每个功能。
1. Model the access pattern first
1. 先建模访问模式
Before touching code, answer:
- Is the data public, user-scoped, org-scoped, or admin-only?
- Will the list stay small, or should it paginate?
- Which fields are lookup keys and therefore need indexes?
- Does any step require an external API, AI SDK, Stripe, or Node API?
编写代码前,先明确以下问题:
- 数据是公开的、用户专属的、组织专属的还是仅管理员可见?
- 列表数据量是否会增长,是否需要分页?
- 哪些字段是查找键,因此需要索引?
- 是否有步骤需要调用外部API、AI SDK、Stripe或Node API?
2. Design the schema
2. 设计Schema
Add or extend before the function layer whenever the model is stabilising.
convex/schema.tsUse references/schema-and-indexes.md for:
- flat relational modelling,
- foreign-key indexing,
- compound indexes around actual query shapes,
- bounded array guidance,
- and pagination thresholds.
当数据模型稳定时,先在中添加或扩展Schema。
convex/schema.ts参考references/schema-and-indexes.md获取以下内容:
- 扁平关系建模,
- 外键索引,
- 围绕实际查询形状的复合索引,
- 有界数组指导,
- 分页阈值。
3. Implement backend functions
3. 实现后端函数
Use references/functions.md for the detailed patterns.
Default rules:
- for deterministic reads.
query - for writes.
mutation - or
actionfor external APIs, third-party SDKs, or Node-only code.internalAction - or
internalQueryfor logic that should never be callable from the client.internalMutation
参考references/functions.md获取详细模式。
默认规则:
- 用于确定性读取操作。
query - 用于写入操作。
mutation - 或
action用于外部API、第三方SDK或仅Node可用的代码。internalAction - 或
internalQuery用于不应被客户端调用的逻辑。internalMutation
4. Enforce access on the backend
4. 在后端强制访问控制
If the feature is not public, do one of these:
- explicit checks in each function, or
ctx.auth.getUserIdentity() - reusable custom wrappers via .
convex-helpers
See references/auth.md and references/components-and-helpers.md.
若功能非公开,选择以下方式之一:
- 在每个函数中显式检查,或
ctx.auth.getUserIdentity() - 通过使用可复用的自定义封装。
convex-helpers
查看references/auth.md和references/components-and-helpers.md。
5. Wire the frontend
5. 连接前端
Use references/frontend-patterns.md.
Always handle:
- loading: ,
useQuery(...) === undefined - empty state,
- mutation pending state where relevant,
- recoverable errors,
- and pagination for unbounded lists.
参考references/frontend-patterns.md。
始终处理以下状态:
- 加载状态:,
useQuery(...) === undefined - 空状态,
- 相关的变更等待状态,
- 可恢复错误,
- 无限制列表的分页。
6. Validate the slice
6. 验证功能切片
Before finishing:
- run the validator with the project root,
- run lint and typecheck if the project has them,
- verify the feature on device or simulator,
- and update or add indexes before shipping.
完成前需执行:
- 针对项目根目录运行验证脚本,
- 若项目配置了代码检查和类型校验,执行相关命令,
- 在设备或模拟器上验证功能,
- 发布前更新或添加索引。
Workflow C — Authentication and authorization
工作流C — 认证与授权
Pick one auth story and keep the stack coherent.
选择一种认证方案并保持技术栈一致性。
Option 1: Clerk
选项1:Clerk
Good when the app already uses Clerk or wants a polished auth product.
适用于应用已使用Clerk或需要成熟认证产品的场景。
Option 2: Convex Auth
选项2:Convex Auth
Good when you want a Convex-native auth stack and are comfortable adopting a beta library.
适用于希望使用Convex原生认证栈且愿意采用Beta版本库的场景。
Option 3: Existing JWT or OIDC provider
选项3:现有JWT或OIDC提供者
Good when the product already depends on Auth0, WorkOS, a company IdP, or another OIDC flow.
适用于产品已依赖Auth0、WorkOS、企业IdP或其他OIDC流程的场景。
Rules regardless of provider
无论选择哪种提供者都需遵守的规则
- Backend authorization is mandatory; client-side gating is only for UX.
- If you persist users in Convex, index by a stable identifier such as .
tokenIdentifier - Check ownership, organisation membership, or role on every protected function.
- Prefer helper functions or custom wrappers instead of repeating auth boilerplate.
- Use internal functions for privileged internal-only operations.
Read references/auth.md for a decision matrix and implementation patterns.
- 后端授权是强制要求;客户端限制仅用于优化用户体验。
- 若在Convex中存储用户信息,需通过稳定标识符(如)建立索引。
tokenIdentifier - 在每个受保护函数中检查所有权、组织成员身份或角色。
- 优先使用辅助函数或自定义封装,避免重复编写认证模板代码。
- 将特权内部操作置于内部函数中。
阅读references/auth.md获取决策矩阵和实现模式。
Workflow D — File uploads from Expo
工作流D — 从Expo上传文件
Use Convex upload URLs rather than trying to push raw files through a mutation.
Recommended flow:
- public or protected mutation returns ,
ctx.storage.generateUploadUrl() - client loads the local URI with
file://and converts it to afetch(uri),Blob - client s the blob to the upload URL,
POST - second mutation stores the returned plus app-specific metadata,
storageId - optional scheduled or action-based post-processing happens afterwards.
Read references/file-uploads.md.
使用Convex上传URL,而非尝试通过变更操作直接推送原始文件。
推荐流程:
- 公开或受保护的变更操作返回,
ctx.storage.generateUploadUrl() - 客户端使用加载本地
fetch(uri)URI并转换为file://,Blob - 客户端将Blob通过请求上传至该URL,
POST - 第二个变更操作存储返回的及应用特定元数据,
storageId - 可选的定时或基于动作的后处理操作在之后执行。
阅读references/file-uploads.md。
Workflow E — Scale and harden
工作流E — 扩展与强化
Once the baseline works, raise the quality bar.
基线整合完成后,提升项目质量标准。
Performance
性能优化
- Replace scans with indexed queries where possible.
.filter() - Replace unbounded with
.collect(),take, or paginated queries.first - Use for growing feeds, notifications, and infinite-scroll screens.
usePaginatedQuery - Push repeated or reusable feature areas into Convex components when boundaries are clear.
- 尽可能用索引查询替代扫描。
.filter() - 用、
take或分页查询替代无限制的first。.collect() - 针对增长型信息流、通知及无限滚动屏幕使用。
usePaginatedQuery - 当边界清晰时,将重复或可复用的功能区域封装为Convex组件。
Safety
安全性强化
- Add validators consistently.
- Keep privileged logic behind internal functions.
- Use or clear return shapes for expected failures.
ConvexError - Never trust IDs from the client without checking ownership or membership.
- 持续添加验证器。
- 将特权逻辑置于内部函数之后。
- 使用或清晰的返回形状处理预期错误。
ConvexError - 绝不信任来自客户端的ID,需先检查所有权或成员身份。
Maintainability
可维护性提升
- Turn on .
@convex-dev/eslint-plugin - Use TypeScript strict mode.
- Keep wrappers thin and move shared logic into plain TypeScript helpers.
- Separate action files from regular runtime files.
"use node"
Read references/production-checklist.md.
- 启用。
@convex-dev/eslint-plugin - 使用TypeScript严格模式。
- 保持封装层简洁,将共享逻辑移至纯TypeScript辅助函数中。
- 将动作文件与常规运行时文件分离。
"use node"
阅读references/production-checklist.md。
Workflow F — Migrations
工作流F — 迁移
When changing a live schema, prefer additive transitions.
Default migration strategy:
- add new fields or tables in a backwards-compatible way,
- dual-read or dual-write if the shape is changing,
- backfill existing documents in idempotent batches,
- switch readers and writers,
- then remove the old shape.
Use internal functions or scheduled jobs for backfills, and keep migrations restart-safe.
Read references/migrations.md.
修改已上线的Schema时,优先采用增量过渡策略。
默认迁移策略:
- 以向后兼容的方式添加新字段或表,
- 若数据结构变更,采用双读或双写模式,
- 以幂等批次回填现有文档,
- 切换读取和写入逻辑至新结构,
- 移除旧数据结构。
使用内部函数或定时任务进行回填,确保迁移可重启。
阅读references/migrations.md。
Fast troubleshooting path
快速故障排查路径
If the app is broken, check these in order:
- Is running and free of TypeScript errors?
npx convex dev - Does contain
.env.local?EXPO_PUBLIC_CONVEX_URL - Was Metro restarted after the env file changed?
- Is there exactly one ?
ConvexReactClient - Is the provider mounted at the real root?
- Does exist, and are imports pointing at it correctly?
convex/_generated/api - Are public functions missing or
argsvalidators?returns - Is a query using ,
Date.now(), or unbounded.filter()?.collect() - Is a file incorrectly mixing queries or mutations?
"use node" - Is auth mismatched between the client provider and the backend config?
See references/troubleshooting.md.
若应用出现故障,按以下顺序检查:
- 是否在运行且无TypeScript错误?
npx convex dev - 是否包含
.env.local?EXPO_PUBLIC_CONVEX_URL - 环境文件变更后是否重启了Metro?
- 是否仅存在一个?
ConvexReactClient - 提供者是否挂载在真正的根节点?
- 是否存在,且导入路径正确?
convex/_generated/api - 公共函数是否缺失或
args验证器?returns - 查询是否使用了、
Date.now()或无限制的.filter()?.collect() - 文件是否错误地混合了查询或变更逻辑?
"use node" - 客户端提供者与后端配置的认证是否不匹配?
查看references/troubleshooting.md。
Available scripts
可用脚本
-
scripts/validate_project.py- Validates the project rooted at or, if copied into a repo, the current working tree.
--root - Validates Expo and Convex dependencies.
- Checks env files, provider wiring, generated code, validator presence, misuse, and common query anti-patterns.
"use node" - Supports ,
--json, and--root.--fail-on-warning
- Validates the project rooted at
-
scripts/scaffold_tasks_example.py- Dry-run by default.
- Can generate ,
sampleData.jsonl,convex/schema.ts, and an optional Expo screen file.convex/tasks.ts - Supports ,
--write,--overwrite, and--ui-file.--json
-
scripts/validate_project.py- 验证指定的项目,若复制到仓库中则验证当前工作目录。
--root - 验证Expo和Convex依赖。
- 检查环境文件、提供者配置、生成代码、验证器存在性、误用及常见查询反模式。
"use node" - 支持、
--json和--root参数。--fail-on-warning
- 验证
-
scripts/scaffold_tasks_example.py- 默认执行空运行。
- 可生成、
sampleData.jsonl、convex/schema.ts及可选的Expo屏幕文件。convex/tasks.ts - 支持、
--write、--overwrite和--ui-file参数。--json
References
参考文档
Load only the file that matches the current task.
- references/eas-env.md — local envs, EAS envs, and deployment URL handling.
- references/tasks-example.md — canonical minimal example for the stack.
- references/schema-and-indexes.md — schema design, indexes, query shape mapping, and pagination triggers.
- references/functions.md — query, mutation, action, internal function, validators, and runtime boundaries.
- references/frontend-patterns.md — provider placement, hook usage, loading and error states, and paginated lists.
- references/auth.md — Clerk, Convex Auth, JWT or OIDC, user mapping, and server-side authorization.
- references/file-uploads.md — upload URLs, Expo URI handling, metadata storage, and post-processing.
- references/components-and-helpers.md — Convex components and patterns.
convex-helpers - references/migrations.md — additive rollout, backfills, dual reads and writes, and batched migrations.
- references/production-checklist.md — pre-release hardening checklist.
- references/troubleshooting.md — common failures and exact fixes.
- references/evaluation.md — how to use the bundled trigger and output eval files.
- references/sources.md — upstream docs and materials used for this rewrite.
仅加载与当前任务匹配的文件。
- references/eas-env.md — 本地环境、EAS环境及部署URL处理。
- references/tasks-example.md — 该技术栈的标准最小示例。
- references/schema-and-indexes.md — Schema设计、索引、查询形状映射及分页触发条件。
- references/functions.md — 查询、变更、动作、内部函数、验证器及运行时边界。
- references/frontend-patterns.md — 提供者放置、钩子使用、加载与错误状态及分页列表。
- references/auth.md — Clerk、Convex Auth、JWT或OIDC、用户映射及服务端授权。
- references/file-uploads.md — 上传URL、Expo URI处理、元数据存储及后处理。
- references/components-and-helpers.md — Convex组件及模式。
convex-helpers - references/migrations.md — 增量发布、回填、双读双写及批量迁移。
- references/production-checklist.md — 发布前强化清单。
- references/troubleshooting.md — 常见故障及具体修复方案。
- references/evaluation.md — 如何使用捆绑的触发器和输出评估文件。
- references/sources.md — 本指南重写所参考的上游文档及资料。