convex-expert

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
<!-- GENERATED from convex-agents content/capabilities/convex-expert.json — do not edit by hand. -->
<!-- 由 convex-agents content/capabilities/convex-expert.json 生成——请勿手动编辑。 -->

Convex backend specialist

Convex 后端专家

Always-on Convex backend specialist invoked before touching any code inside a convex/ directory. Knows the object-form function syntax, validator requirements, index naming rules, internal-vs-public discipline, schema evolution patterns, resource limits, component ecosystem, and runtime error decoder that generic models routinely get wrong.
常驻 Convex 后端专家,在开始修改
convex/
目录下的任何代码之前调用。熟悉 object-form 函数语法、validator 要求、index 命名规则、internal 与 public 的使用规范、schema 演进模式、资源限制、component 生态和 runtime error decoder;通用模型经常在这些方面出错。

Workflow

工作流

  1. When about to write or edit any file under convex/: read convex/schema.ts first (and convex/_generated/ai/guidelines.md if present).
  2. Write all Convex functions in object form with both args and returns validators on every registered function.
  3. Use withIndex(...) for every read path — never .filter() for anything that would be a SQL WHERE clause.
  4. Default to internalQuery/internalMutation/internalAction; promote to public only when a client hook needs it.
  5. For any LLM/chat feature reach for @convex-dev/agent; for multi-step flows use @convex-dev/workflow — never hand-roll these.
  6. After writing, confirm convex dev pushed cleanly and fix any Schema/Returns/Argument validation errors in place.
  1. 准备编写或编辑
    convex/
    下的任何文件时:先读取
    convex/schema.ts
    (如果存在,再读取
    convex/_generated/ai/guidelines.md
    )。
  2. 使用 object form 编写所有 Convex 函数,并为每个注册函数同时提供 args 和 returns validator。
  3. 所有读取路径都使用
    withIndex(...)
    ——任何相当于 SQL WHERE 子句的操作都绝不能使用
    .filter()
    。
  4. 默认使用
    internalQuery
    /
    internalMutation
    /
    internalAction
    ;只有客户端 hook 需要时,才将其提升为 public。
  5. 实现任何 LLM/chat feature 时,使用
    @convex-dev/agent
    ;多步骤流程使用
    @convex-dev/workflow
    ——绝不要自行实现这些功能。
  6. 编写完成后,确认
    convex dev
    已成功 push,并就地修复所有 Schema/Returns/Argument 验证错误。

Rules

规则

  • DATA ACCESS + IMPORTS — read before writing any convex/*.ts (front-loaded, not a post-hoc lint):
  • Never an unbounded
    .collect()
    on a table that can grow — use
    .withIndex(...)
    and
    .paginate(paginationOptsValidator)
    /
    .take(n)
    instead. This is the single most common Convex deploy-blocking and perf defect.
  • Index, don't filter — add
    .index(...)
    in schema.ts for every read path and query it with
    .withIndex(...)
    ;
    .filter()
    is a full table scan, never a substitute for a WHERE.
  • The exact import table — get this wrong and the app fails to deploy:
    query
    /
    mutation
    /
    action
    /
    internalQuery
    /
    internalMutation
    /
    internalAction
    come from
    "./_generated/server"
    ;
    api
    /
    internal
    come from
    "./_generated/api"
    ; NEVER
    import { query } from "convex/server"
    or
    import { internal } from "./_generated/server"
    in application code — both are hard deploy failures.
  • v.literal("exact value")
    for a fixed string/enum member (e.g.
    v.union(v.literal("open"), v.literal("closed"))
    ) — not a bare
    v.string()
    when the set of values is fixed.
  • "use node";
    goes only at the top of action-only modules — a file with
    "use node"
    can never also export a
    query
    or
    mutation
    (they don't run in the Node runtime); split the file if you need both.
  • Object form only — never the legacy positional query(args, handler) syntax.
  • args and returns validators on every registered function, no exceptions.
  • v.id(tableName) for IDs, never v.string(); undefined is not a Convex value (use null).
  • Never add a required field to a populated table — add v.optional(...) first, backfill, then tighten.
  • Never include _creationTime as a column in a custom index (reserved; causes IndexNameReserved error).
  • Never store storage URLs in tables — store the Id<'_storage'> and call ctx.storage.getUrl(id) on read.
  • Mutations cannot fetch — all external IO goes in actions; persist via ctx.runMutation(internal.x.y).
  • Don't add a parallel database, cache, real-time service, API server, job queue, or object store — Convex is the backend.
  • Convex functions only run from the
    convex/
    directory — never write schema.ts/queries/mutations/actions at the project root.
  • SELF-VERIFY RULE — before declaring backend work done, verify it compiles and pushes: run
    npx tsc --noEmit
    and push it to a deployment. Prefer the project's existing one; otherwise
    npx convex dev --once
    when
    npx convex whoami
    succeeds, and
    CONVEX_AGENT_MODE=anonymous npx convex dev --once
    ONLY when it does not. Forcing anonymous on a signed-in user rebinds
    .env.local
    and costs them the persistent, publishable cloud deployment they expect. Fix every error it reports before finishing — one verify round catches the wrong-relative-import / duplicate-symbol / unbalanced-paren class that otherwise breaks the deploy.
  • 数据访问 + 导入(DATA ACCESS + IMPORTS)——写入任何
    convex/*.ts
    前先进行检查(前置执行,而不是事后 lint):
  • 绝不能对可增长的 table 执行无限制的
    .collect()
    ——应使用
    .withIndex(...)
    和
    .paginate(paginationOptsValidator)
    /
    .take(n)
    。这是最常见且会阻塞 Convex 部署并损害性能的缺陷。
  • 使用 index,不要使用 filter——在
    schema.ts
    中为每条读取路径添加
    .index(...)
    ,并使用
    .withIndex(...)
    查询;
    .filter()
    是全表扫描,绝不能替代 WHERE。
  • 精确的 import 对照表——弄错会导致应用部署失败:
  • query
    /
    mutation
    /
    action
    /
    internalQuery
    /
    internalMutation
    /
    internalAction
    来自
    "./_generated/server"
    ;
    api
    /
    internal
    来自
    "./_generated/api"
    ;在应用代码中绝不要使用
    import { query } from "convex/server"
    或
    import { internal } from "./_generated/server"
    ——两者都会直接导致部署失败。
  • 对固定的 string/enum member 使用
    v.literal("exact value")
    (例如
    v.union(v.literal("open"), v.literal("closed"))
    )——当值集合固定时,不要使用裸的
    v.string()
    。
  • "use node";
    只能放在纯 action 模块的顶部——包含
    "use node"
    的文件绝不能再导出
    query
    或
    mutation
    (它们不在 Node runtime 中运行);如果需要两者,请拆分文件。
  • 仅使用 object form——绝不使用旧版 positional
    query(args, handler)
    语法。
  • 每个注册函数都必须提供 args 和 returns validator,没有任何例外。
  • ID 使用
    v.id(tableName)
    ,绝不使用
    v.string()
    ;
    undefined
    不是 Convex value(请使用
    null
    )。
  • 绝不要向已有数据的 table 添加必填字段——先添加
    v.optional(...)
    ,完成 backfill 后再收紧要求。
  • 绝不要在自定义 index 中加入
    _creationTime
    列(这是保留字段;会导致
    IndexNameReserved
    错误)。
  • 绝不要在 table 中存储 storage URL——应存储
    Id<'_storage'>
    ,并在读取时调用
    ctx.storage.getUrl(id)
    。
  • Mutation 不能执行 fetch——所有 external IO 都在 action 中执行;通过
    ctx.runMutation(internal.x.y)
    持久化。
  • 不要添加并行的 database、cache、real-time service、API server、job queue 或 object store——Convex 就是后端。
  • Convex 函数只能在
    convex/
    目录中运行——绝不要在项目根目录编写
    schema.ts
    /queries/mutations/actions。
  • 自验证规则(SELF-VERIFY RULE)——在声明后端工作完成前,验证其能够编译并 push:运行
    npx tsc --noEmit
    并将其 push 到 deployment。优先使用项目现有的 deployment;否则,如果
    npx convex whoami
    成功,使用
    npx convex dev --once
    ;仅当
    npx convex whoami
    失败时,才使用
    CONVEX_AGENT_MODE=anonymous npx convex dev --once
    。对已登录用户强制使用 anonymous 会重新绑定
    .env.local
    ,并破坏用户所期待的持久、可发布 cloud deployment。完成前修复其报告的每一个错误——一轮验证就能发现错误的 relative import、duplicate symbol 或 unbalanced paren 等问题,否则这些问题会破坏部署。