deepspace

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Build real-time collaborative apps on Cloudflare Workers in one package: SQLite-backed Durable Objects, RBAC, WebSocket subscriptions, Better Auth. Scaffolds with sensible defaults — generouted file-based routing, shadcn-style primitives, Vite + Tailwind v4. Apps deploy to
<name>.app.space
.
在Cloudflare Workers上一键构建实时协作应用:基于SQLite的Durable Objects、RBAC权限控制、WebSocket订阅、Better Auth。脚手架提供合理默认配置——generouted文件路由、shadcn风格组件、Vite + Tailwind v4。应用部署至
<name>.app.space

Quickstart — the development lifecycle

快速入门——开发生命周期

CLI commands, in order. Each step is rerunnable.
dev
and
test
rewrite only the 9 SDK-managed keys in
.dev.vars
(auth + worker URLs + owner JWT + per-app identity token + debug flag); anything else you add — third-party tokens, custom flags — is preserved verbatim across runs and ships to prod as
secret_text
bindings on
deploy
. See "Login, test, deploy" for the contract.
bash
undefined
按顺序执行以下CLI命令,每个步骤均可重复运行。
dev
test
仅重写
.dev.vars
中的9个SDK管理密钥(认证信息+Worker URL+所有者JWT+每个应用的身份令牌+调试标志);您添加的其他内容——第三方令牌、自定义标志——将在运行过程中完整保留,并在
deploy
时作为
secret_text
绑定部署到生产环境。请查看“登录、测试、部署”部分了解具体约定。
bash
undefined

1. Scaffold (no auth required — npm fetches create-deepspace via npx on demand)

1. Scaffold (no auth required — npm fetches create-deepspace via npx on demand)

npm create deepspace@latest <app-name> cd <app-name>
npm create deepspace@latest <app-name> cd <app-name>

<app-name> seeds the directory AND wrangler.toml's
name
(= deploy subdomain),

<app-name> seeds the directory AND wrangler.toml's
name
(= deploy subdomain),

but both are editable after scaffold — see references/architecture.md § App-name

but both are editable after scaffold — see references/architecture.md § App-name

rules. Scaffold into the directory you want; don't scaffold-then-move.

rules. Scaffold into the directory you want; don't scaffold-then-move.

CLI is non-interactive by default (agent-friendly): omitting <app-name> prints

CLI is non-interactive by default (agent-friendly): omitting <app-name> prints

usage and exits 1 instead of prompting on stdin. Pass
--interactive
/
-i

usage and exits 1 instead of prompting on stdin. Pass
--interactive
/
-i

for the prompt-driven wizard. Probe with
--help
/
-h
(plain stdout, no

for the prompt-driven wizard. Probe with
--help
/
-h
(plain stdout, no

ANSI) or
--version
/
-v
before invoking when scripting.

ANSI) or
--version
/
-v
before invoking when scripting.

Three invocation forms work — the scaffolder is permissive about target state:

Three invocation forms work — the scaffolder is permissive about target state:

a) From a parent dir, target does not exist: creates <app-name>/ fresh.

a) From a parent dir, target does not exist: creates <app-name>/ fresh.

b) From a parent dir, target is near-empty: scaffolds in-place into <app-name>/.

b) From a parent dir, target is near-empty: scaffolds in-place into <app-name>/.

c) From inside the target dir (any near-empty): scaffolds in-place into cwd; pass
.

c) From inside the target dir (any near-empty): scaffolds in-place into cwd; pass
.

to inherit the dir's name (lowercased).

to inherit the dir's name (lowercased).

"Near-empty" = only boilerplate is allowed: .git, .gitignore, .gitattributes,

"Near-empty" = only boilerplate is allowed: .git, .gitignore, .gitattributes,

.github/, LICENSE*, README*, any *.md, .vite, .wrangler, .dev.vars, .DS_Store.

.github/, LICENSE*, README*, any *.md, .vite, .wrangler, .dev.vars, .DS_Store.

Anything else triggers
Directory <name> already exists
and the scaffolder bails.

Anything else triggers
Directory <name> already exists
and the scaffolder bails.

.git
is allowed but not required — empty / unversioned dirs scaffold fine,

.git
is allowed but not required — empty / unversioned dirs scaffold fine,

and a trailing
git init
runs only when no
.git
exists yet.

and a trailing
git init
runs only when no
.git
exists yet.

2. One-time login — opens browser, polls up to 10 minutes. Interactive; pause and

2. One-time login — opens browser, polls up to 10 minutes. Interactive; pause and

have the user complete the OAuth flow at the keyboard.

have the user complete the OAuth flow at the keyboard.

npx deepspace login
npx deepspace login

3. Local dev (Vite + worker in-process; HMR on localhost:5173, --strictPort fails loudly on clash)

3. Local dev (Vite + worker in-process; HMR on localhost:5173, --strictPort fails loudly on clash)

npx deepspace dev # default npx deepspace dev --port 5180 # parallel apps npx deepspace dev --prod # same UI, but workers point at production
npx deepspace dev # default npx deepspace dev --port 5180 # parallel apps npx deepspace dev --prod # same UI, but workers point at production

3a. Clean up leaked workerd/vite (your own — never a sibling session's):

3a. Clean up leaked workerd/vite (your own — never a sibling session's):

npx deepspace kill # kills listener on 5173 + its workerd children npx deepspace kill --port 5180 # different port npx deepspace kill --all # sweeps every workerd/wrangler/vite on the box
npx deepspace kill # kills listener on 5173 + its workerd children npx deepspace kill --port 5180 # different port npx deepspace kill --all # sweeps every workerd/wrangler/vite on the box

4. Provision test accounts (one-time per machine; pool is shared across all apps, hard cap of 10)

4. Provision test accounts (one-time per machine; pool is shared across all apps, hard cap of 10)

npx deepspace test-accounts list # check what's already there npx deepspace test-accounts create --email <…@deepspace.test> --password <p> --name <n>
npx deepspace test-accounts list # check what's already there npx deepspace test-accounts create --email <…@deepspace.test> --password <p> --name <n>

5. Run tests (auto-installs Playwright + chromium on first run; always uses dev workers)

5. Run tests (auto-installs Playwright + chromium on first run; always uses dev workers)

npx deepspace test # default suite (smoke + api) npx deepspace test e2e # all Playwright specs npx deepspace test unit # vitest
npx deepspace test # default suite (smoke + api) npx deepspace test e2e # all Playwright specs npx deepspace test unit # vitest

5a. Capture a Playwright screenshot of any URL (shares the same chromium install as
test
).

5a. Capture a Playwright screenshot of any URL (shares the same chromium install as
test
).

npx deepspace screenshot http://localhost:5173/ out.png npx deepspace screenshot http://localhost:5173/ out.png --full-page --wait-for-timeout 500
npx deepspace screenshot http://localhost:5173/ out.png npx deepspace screenshot http://localhost:5173/ out.png --full-page --wait-for-timeout 500

6. Install scaffold features

6. Install scaffold features

MUST run
add --list
in THIS session before hand-rolling any non-trivial UI —

MUST run
add --list
in THIS session before hand-rolling any non-trivial UI —

building from scratch when a scaffold feature exists is a defect. Never claim

building from scratch when a scaffold feature exists is a defect. Never claim

to have run it without actually executing it and quoting the output; prior

to have run it without actually executing it and quoting the output; prior

knowledge of the feature set does not count.

knowledge of the feature set does not count.

npx deepspace add --list # REQUIRED first — discover available features npx deepspace add --info <name> # inspect what a feature installs npx deepspace add <feature> # install into current app
npx deepspace add --list # REQUIRED first — discover available features npx deepspace add --info <name> # inspect what a feature installs npx deepspace add <feature> # install into current app

7. Discover & test platform integrations from the CLI

7. Discover & test platform integrations from the CLI

Discovery is free (no login, no app dir, no dev server) — agents can probe the

Discovery is free (no login, no app dir, no dev server) — agents can probe the

catalog cold. Only
invoke <ep> --body
actually calls the endpoint and is

catalog cold. Only
invoke <ep> --body
actually calls the endpoint and is

billed to the logged-in user.

billed to the logged-in user.

npx deepspace integrations list # NO AUTH — full catalog npx deepspace integrations info openai/chat-completion # NO AUTH — schema + example body for one endpoint npx deepspace invoke openai/chat-completion --body '{...}' # AUTH REQUIRED — actually call it (billed to caller) npx deepspace invoke openai/chat-completion --body-file - # AUTH REQUIRED — body via stdin (cat req.json | …)
npx deepspace integrations list # NO AUTH — full catalog npx deepspace integrations info openai/chat-completion # NO AUTH — schema + example body for one endpoint npx deepspace invoke openai/chat-completion --body '{...}' # AUTH REQUIRED — actually call it (billed to caller) npx deepspace invoke openai/chat-completion --body-file - # AUTH REQUIRED — body via stdin (cat req.json | …)

npx deepspace invoke --list
and
--info
are aliases for the no-auth forms above.

npx deepspace invoke --list
and
--info
are aliases for the no-auth forms above.

8. Deploy (subdomain comes from wrangler.toml's
name
field — rename there, not at deploy time)

8. Deploy (subdomain comes from wrangler.toml's
name
field — rename there, not at deploy time)

npx deepspace deploy # → <wrangler.name>.app.space
npx deepspace deploy # → <wrangler.name>.app.space

9. (Optional) Buy & attach a custom domain to the deployed app

9. (Optional) Buy & attach a custom domain to the deployed app

npx deepspace domain search <query> # find available domains and prices npx deepspace domain buy <domain> # buy via Stripe Checkout (browser opens) npx deepspace domain list # list domains you own npx deepspace domain attach <domain> --app <name> # re-point a domain at a different app
npx deepspace domain search <query> # find available domains and prices npx deepspace domain buy <domain> # buy via Stripe Checkout (browser opens) npx deepspace domain list # list domains you own npx deepspace domain attach <domain> --app <name> # re-point a domain at a different app

10. (Optional) Publish the deployed app to the DeepSpace community library

10. (Optional) Publish the deployed app to the DeepSpace community library

npx deepspace library publish [--name "<title>"] [--description "<short>"] [--category <cat>] npx deepspace library unpublish <handle>
npx deepspace library publish [--name "<title>"] [--description "<short>"] [--category <cat>] npx deepspace library unpublish <handle>

11. (Optional) Provision a DeepSpace-managed GitHub repo for users without their own GitHub account

11. (Optional) Provision a DeepSpace-managed GitHub repo for users without their own GitHub account

npx deepspace managed-repos list npx deepspace managed-repos create <app-name> # platform-owned private repo npx deepspace managed-repos token <repo-id> # short-lived clone token npx deepspace managed-repos delete <repo-id> --yes # per-day quota applies

**Login state is shared across all apps on the machine.** One `deepspace login` covers `dev`, `test-accounts`, and `deploy` for any app. Probe login state with `npx deepspace whoami` (`--json` for agents); don't stat `~/.deepspace/session` — that's a CLI implementation detail. Re-login only when `whoami` reports not-signed-in or the session has expired. See "Login, test, deploy" below for the full contract.
npx deepspace managed-repos list npx deepspace managed-repos create <app-name> # platform-owned private repo npx deepspace managed-repos token <repo-id> # short-lived clone token npx deepspace managed-repos delete <repo-id> --yes # per-day quota applies

**登录状态在同一台机器的所有应用间共享**。一次`deepspace login`即可覆盖任意应用的`dev`、`test-accounts`和`deploy`操作。使用`npx deepspace whoami`(代理可添加`--json`参数)查看登录状态;不要通过查看`~/.deepspace/session`文件判断——这是CLI的实现细节。仅当`whoami`显示未登录或会话过期时,才需要重新登录。请查看下方“登录、测试、部署”部分了解完整约定。

Two imports

两个核心导入

typescript
// Frontend (React)
import { RecordProvider, RecordScope, useQuery, useMutations, useAuth } from 'deepspace'

// Worker (Cloudflare Worker)
import { RecordRoom, verifyJwt, CHANNELS_SCHEMA } from 'deepspace/worker'
Two more entry points exist for narrower use cases:
'deepspace/server'
for worker-side helpers backed by the platform (payments helpers +
captureScreenshot
— see
references/payments.md
/
references/sdk-reference.md
), and
'deepspace/testing'
for the Playwright multi-user fixture (see
references/testing.md
).
typescript
// Frontend (React)
import { RecordProvider, RecordScope, useQuery, useMutations, useAuth } from 'deepspace'

// Worker (Cloudflare Worker)
import { RecordRoom, verifyJwt, CHANNELS_SCHEMA } from 'deepspace/worker'
针对更细分的使用场景,还有另外两个入口:
'deepspace/server'
用于平台提供的Worker端辅助工具(支付辅助函数+
captureScreenshot
——详见
references/payments.md
/
references/sdk-reference.md
),以及**
'deepspace/testing'
** 用于Playwright多用户测试夹具(详见
references/testing.md
)。

Project layout

项目结构

The scaffold generates a Vite + Cloudflare-Worker app. Files you'll touch most often:
PathPurpose
worker.ts
Hono app worker;
__DO_MANIFEST__
declares 6 DO classes (
AppRecordRoom
,
AppYjsRoom
,
AppCanvasRoom
,
AppPresenceRoom
,
AppCronRoom
,
AppJobRoom
). AI chat routes live in
src/ai/chat-routes.ts
(registered via
registerAiChatRoutes(app, resolveAuth)
) — edit there, not here. Edit
worker.ts
itself when adding new DO classes / WebSocket routes, customizing
AppRecordRoom
options, adding custom HTTP routes, or wiring cross-app proxies.
wrangler.toml
Cloudflare config.
name
becomes the
<name>.app.space
subdomain — must match
^[a-z0-9](?:-?[a-z0-9])+$
(2-63 chars, lowercase).
dev
and
deploy
fail-fast on a non-canonical
name
now
(was silent canonicalization in earlier SDKs) — fix the field rather than ignoring the error.
run_worker_first = ["/api/*", "/ws/*", "/internal/*", "/v1/*", "/_deepspace/*"]
/v1/*
is included so OpenAI-compatible routes mounted in
worker.ts
resolve before the SPA fallback;
/_deepspace/*
is the same-origin browser proxy the subscriptions / charges hooks call (don't strip it). Apps can append their own prefixes (
/oauth/*
,
/preview/*
,
/.well-known/*
); the CLI strips the reserved set and forwards the rest. Declare custom Cloudflare bindings here (vectorize / r2 / kv / d1 / queue / ai / browser_rendering / hyperdrive / analytics_engine); use
"auto"
as the id to auto-provision. →
references/bindings.md
.
src/pages/_app.tsx
Provider stack:
ToastProvider → DeepSpaceAuthProvider → AuthBoot → RecordProvider → RecordScope
. Extend, don't replace.
src/pages/
File-based routes via generouted.
(protected)/
is the gated route group.
src/schemas.ts
+
src/schemas/
Collection schemas. Ships
usersSchema
+
settingsSchema
.
src/themes.ts
+
src/themes.css
15 theme presets; active one set on
<html data-theme>
in
index.html
.
src/styles.css
Tailwind v4 entry;
@theme
block holds the slate baseline.
src/nav.ts
Top-nav entries — add new pages here so
Navigation.tsx
picks them up.
src/constants.ts
APP_NAME
,
SCOPE_ID = "app:${APP_NAME}"
, role re-exports.
src/actions/index.ts
Server-action handlers.
src/cron.ts
Scheduled tasks for
AppCronRoom
.
src/jobs.ts
Background-job handlers for
AppJobRoom
(durable work outliving the HTTP response).
src/integrations.ts
Per-integration billing config (
developer
vs
user
).
src/ai/tools.ts
System prompt + tool allowlist for
/api/ai/chat
. Tools are not read-only by default — the scaffold ships
records.create
/
records.update
/
records.delete
alongside reads. Per-collection RBAC at the DO is the actual security boundary; trim the allowlist if you want a stricter assistant.
src/ai/chat-routes.ts
Hono handlers for the 4 AI chat endpoints (
POST /api/ai/chats
,
PATCH /api/ai/chats/:id
,
DELETE /api/ai/chats/:id
,
POST /api/ai/chat
— the streaming turn). Edit to switch model/provider, change context-window compaction, or extend the tool surface.
tests/
Playwright
smoke.spec.ts
/
api.spec.ts
/
collab.spec.ts
+
playwright.config.ts
.
脚手架会生成一个Vite + Cloudflare Worker应用。您最常接触的文件如下:
路径用途
worker.ts
Hono应用Worker;
__DO_MANIFEST__
声明了6个DO类(
AppRecordRoom
AppYjsRoom
AppCanvasRoom
AppPresenceRoom
AppCronRoom
AppJobRoom
)。AI聊天路由位于
src/ai/chat-routes.ts
(通过
registerAiChatRoutes(app, resolveAuth)
注册)——请在此文件中编辑,不要修改
worker.ts
本身。仅当添加新的DO类/WebSocket路由、自定义
AppRecordRoom
配置、添加自定义HTTP路由或配置跨应用代理时,才需要编辑
worker.ts
wrangler.toml
Cloudflare配置文件。
name
字段会成为
<name>.app.space
子域名——必须匹配
^[a-z0-9](?:-?[a-z0-9])+$
(2-63个字符,小写)。现在
dev
deploy
会对不符合规范的
name
直接报错
(早期SDK会自动规范化但不提示)——请修改该字段,不要忽略错误。
run_worker_first = ["/api/*", "/ws/*", "/internal/*", "/v1/*", "/_deepspace/*"]
——包含
/v1/*
是为了让
worker.ts
中挂载的OpenAI兼容路由在SPA fallback之前解析;
/_deepspace/*
是订阅/收费钩子调用的同域浏览器代理(不要删除)。应用可以添加自己的前缀(
/oauth/*
/preview/*
/.well-known/*
);CLI会保留预留前缀并转发其余部分。在此处声明自定义Cloudflare绑定(vectorize / r2 / kv / d1 / queue / ai / browser_rendering / hyperdrive / analytics_engine);使用
"auto"
作为id可自动配置。→
references/bindings.md
src/pages/_app.tsx
Provider栈:
ToastProvider → DeepSpaceAuthProvider → AuthBoot → RecordProvider → RecordScope
请扩展,不要替换
src/pages/
通过generouted实现的文件路由。
(protected)/
是受保护的路由组。
src/schemas.ts
+
src/schemas/
集合Schema。默认包含
usersSchema
+
settingsSchema
src/themes.ts
+
src/themes.css
15个主题预设;当前激活主题在
index.html
<html data-theme>
中设置。
src/styles.css
Tailwind v4入口文件;
@theme
块包含slate基线样式。
src/nav.ts
顶部导航条目——在此添加新页面,
Navigation.tsx
会自动识别。
src/constants.ts
APP_NAME
SCOPE_ID = "app:${APP_NAME}"
、角色重导出。
src/actions/index.ts
服务器动作处理器。
src/cron.ts
AppCronRoom
的定时任务。
src/jobs.ts
AppJobRoom
的后台任务处理器(独立于HTTP响应的持久化任务)。
src/integrations.ts
每个集成的计费配置(
developer
vs
user
)。
src/ai/tools.ts
/api/ai/chat
的系统提示词+工具白名单。默认情况下工具不是只读的——脚手架包含
records.create
/
records.update
/
records.delete
以及读取操作。DO层面的按集合RBAC是实际的安全边界;如果需要更严格的助手权限,请缩减白名单。
src/ai/chat-routes.ts
4个AI聊天端点的Hono处理器(
POST /api/ai/chats
PATCH /api/ai/chats/:id
DELETE /api/ai/chats/:id
POST /api/ai/chat
——流式对话)。编辑此文件可切换模型/提供商、修改上下文窗口压缩逻辑或扩展工具范围。
tests/
Playwright测试文件
smoke.spec.ts
/
api.spec.ts
/
collab.spec.ts
+
playwright.config.ts

Build a new app

构建新应用

Steps run in dependency order. Each links its deep-dive reference; load that reference only when you reach the step.
  1. Scaffold — see Quickstart.
  2. Schemas — define collections with
    name
    ,
    columns
    ,
    permissions
    . Add to
    src/schemas/
    , register in
    src/schemas.ts
    alongside
    usersSchema
    (required — uses
    USERS_COLUMNS
    from
    deepspace/worker
    ;
    useUser
    /
    useUsers
    / auth depend on a
    'users'
    collection with this exact shape, so never rename or remove it). The scaffold also ships
    settingsSchema
    as a starter admin key/value store — keep, customize, or drop freely; no SDK feature depends on it. For messaging, also add
    CHANNELS_SCHEMA
    /
    MESSAGES_SCHEMA
    /
    REACTIONS_SCHEMA
    from
    deepspace/worker
    . →
    references/schemas.md
  3. Cross-app data sharing? — if the app needs to read/write
    workspace:*
    ,
    dir:*
    , or
    conv:*
    scopes shared across DeepSpace apps (e.g., the email-handle workspace, cross-app inbox), the scaffolded
    /ws/:roomId
    handler routes everything to the local DO and won't see shared data. Add the
    PLATFORM_WORKER
    proxy edit. →
    references/architecture.md
    § Cross-app shared scopes. Skip otherwise.
  4. Auth model — pick public, gated, or mixed (the default; gated routes drop into
    src/pages/(protected)/
    ). →
    references/auth.md
  5. Theme — pick a preset on
    <html data-theme="...">
    in
    index.html
    , update
    <title>
    /favicon. Don't ship the default
    slate
    .
    references/uiux.md
    §2
  6. Pages and features — pages in
    src/pages/
    . Ready-made features ship inside the
    deepspace
    SDK (
    node_modules/deepspace/features/
    ); install with
    npx deepspace add <feature>
    (use
    --list
    to enumerate). →
    references/uiux.md
    for UI primitives.
  7. Tests — read
    references/testing.md
    and apply the Step 8 checklist before extending
    smoke.spec.ts
    /
    api.spec.ts
    /
    collab.spec.ts
    . Multi-user features need a 2-user Playwright spec, not just
    tsc
    or unit tests.
  8. Deploy
    npx deepspace deploy
    . Pre-deploy checklist: home replaced, theme picked, browser-default primitives removed, toasts wired to mutations. →
    references/uiux.md
    §5
For maintenance work on an existing app, jump straight to the relevant reference.
按依赖顺序执行以下步骤,每个步骤都链接了对应的深度参考文档;仅当执行到该步骤时,才需要加载对应的参考文档。
  1. 搭建脚手架——详见快速入门。
  2. 定义Schema——使用
    name
    columns
    permissions
    定义集合。添加到
    src/schemas/
    目录,并在
    src/schemas.ts
    中与
    usersSchema
    一起注册(
    usersSchema
    是必需的——它使用
    deepspace/worker
    中的
    USERS_COLUMNS
    useUser
    /
    useUsers
    / 认证功能依赖名为
    'users'
    且结构完全一致的集合,因此请勿重命名或删除它)。脚手架还提供了
    settingsSchema
    作为初始的管理员键值存储——可保留、自定义或删除;没有SDK功能依赖它。如果需要消息功能,还需添加
    deepspace/worker
    中的
    CHANNELS_SCHEMA
    /
    MESSAGES_SCHEMA
    /
    REACTIONS_SCHEMA
    。→
    references/schemas.md
  3. 跨应用数据共享?——如果应用需要读写DeepSpace应用间共享的
    workspace:*
    dir:*
    conv:*
    范围(例如,邮箱句柄工作区、跨应用收件箱),则脚手架生成的
    /ws/:roomId
    处理器会将所有请求路由到本地DO,无法读取共享数据。需添加
    PLATFORM_WORKER
    代理配置。→
    references/architecture.md
    § 跨应用共享范围。否则可跳过此步骤。
  4. 认证模型——选择公开、 gated 或 混合(默认;gated路由放在
    src/pages/(protected)/
    目录下)。→
    references/auth.md
  5. 主题设置——在
    index.html
    <html data-theme="...">
    中选择一个预设主题,更新
    <title>
    /图标。请勿直接使用默认的
    slate
    主题
    。→
    references/uiux.md
    §2
  6. 页面与功能——页面放在
    src/pages/
    目录下。现成功能包含在
    deepspace
    SDK中(
    node_modules/deepspace/features/
    );使用
    npx deepspace add <feature>
    安装(使用
    --list
    查看所有可用功能)。→
    references/uiux.md
    了解UI组件。
  7. 测试——阅读
    references/testing.md
    并在扩展
    smoke.spec.ts
    /
    api.spec.ts
    /
    collab.spec.ts
    前应用步骤8的检查清单。多用户功能需要2用户Playwright测试,而不仅仅是
    tsc
    或单元测试。
  8. 部署——执行
    npx deepspace deploy
    。部署前检查清单:替换默认首页、选择主题、移除浏览器默认组件、将toast与变更操作关联。→
    references/uiux.md
    §5
对于现有应用的维护工作,可直接跳转到对应的参考文档。

Frontend hooks

前端钩子

The three core auth + data hooks.
useAuth
is universal (every page that has a sign-in state uses it);
useQuery
/
useMutations
show up the moment a page reads or writes a collection. For everything else (messaging, directory, R2, Yjs, presence, canvas, cron monitor, jobs, theme, env), see
references/sdk-reference.md
.
typescript
const { records, status } = useQuery<Item>('items', { where: { status: 'published' }, orderBy: 'createdAt' })
const { create, put, remove } = useMutations<Item>('items')   // create returns Promise<string> (the new recordId — capture it)
const { isSignedIn, isLoaded } = useAuth()                    // primary auth check
Each record is an envelope
{ recordId, data: T, createdBy, createdAt, updatedAt }
. User fields live under
.data
(
r.data.title
, never
r.title
). Pass
r.recordId
to
put
/
remove
.
put
accepts
Partial<T>
— server merges into the existing row (
{...existing, ...patch}
), so send only the fields you're changing (
put(id, { completed: true })
, not the whole spread).
create
still requires the full
T
.
For anything beyond these three (messaging, presence, R2, Yjs, canvas, game rooms, cron, jobs, AI chat, integrations, theming, RBAC), read
references/sdk-reference.md
first; only then drop into
node_modules/deepspace/dist/index.d.ts
(frontend) or
node_modules/deepspace/dist/worker.d.ts
(worker) for exact type signatures. Do not guess hook names or argument shapes.
三个核心的认证+数据钩子。
useAuth
是通用钩子(所有涉及登录状态的页面都会用到);当页面需要读取或写入集合时,会用到
useQuery
/
useMutations
。其他功能(消息、目录、R2、Yjs、在线状态、画布、定时任务监控、作业、主题、环境变量)请查看
references/sdk-reference.md
typescript
const { records, status } = useQuery<Item>('items', { where: { status: 'published' }, orderBy: 'createdAt' })
const { create, put, remove } = useMutations<Item>('items')   // create returns Promise<string> (the new recordId — capture it)
const { isSignedIn, isLoaded } = useAuth()                    // primary auth check
每条记录都是一个信封结构——
{ recordId, data: T, createdBy, createdAt, updatedAt }
。用户字段位于
.data
下(
r.data.title
,不要使用
r.title
)。将
r.recordId
传递给
put
/
remove
方法。
put
接受
Partial<T>
类型参数
——服务器会将其合并到现有行中(
{...existing, ...patch}
),因此只需发送您要修改的字段(
put(id, { completed: true })
,无需发送完整对象)。
create
仍需要完整的
T
类型对象。
除这三个钩子外的其他功能(消息、在线状态、R2、Yjs、画布、游戏房间、定时任务、作业、AI聊天、集成、主题、RBAC),请先阅读
references/sdk-reference.md
;之后再查看
node_modules/deepspace/dist/index.d.ts
(前端)或
node_modules/deepspace/dist/worker.d.ts
(Worker)获取精确的类型签名。请勿猜测钩子名称或参数格式。

Worker-side extensions

Worker端扩展

Seven independent surfaces. Load only what you need:
  • Server actions (privileged writes that bypass caller RBAC) →
    references/server-actions.md
  • AI chat (streamed Claude / OpenAI / Cerebras with multi-turn tool use, persistent chat history, context-window compaction) →
    references/ai-chat.md
  • Cron (scheduled tasks via
    AppCronRoom
    +
    useCronMonitor
    ) →
    references/cron.md
  • Jobs (durable background work via
    AppJobRoom
    +
    useJobs
    — anything that needs to outlive the HTTP response: AI generation, exports, renders) →
    references/jobs.md
  • Payments (Stripe-backed subscriptions, paywalls, one-time products, tips, refunds, cancellation — never hand-roll Stripe; use
    useSubscription
    /
    useCheckout
    /
    requireSubscription
    ) →
    references/payments.md
  • Game rooms (turn/tick game loops, lobby, host-advanced phases,
    useGameRoom
    +
    GameRoom
    DO) →
    references/sdk-reference.md
    § Real-time collab + § Game rooms
  • Custom bindings & metering (Vectorize, AI, R2, KV, D1, Queues, Hyperdrive;
    "auto"
    autoprovisioning;
    runMigrations
    for D1;
    meterAi
    /
    meterVectorize
    per-tenant rollup via the auto-attached
    USAGE_EVENTS
    AE dataset) →
    references/bindings.md
Skip all of these for apps that only need client hooks and
integration.post(...)
.
七个独立的扩展方向,按需加载即可:
  • 服务器动作(绕过调用者RBAC的特权写入)→
    references/server-actions.md
  • AI聊天(支持多轮工具调用、持久化聊天历史、上下文窗口压缩的流式Claude / OpenAI / Cerebras聊天)→
    references/ai-chat.md
  • 定时任务(通过
    AppCronRoom
    +
    useCronMonitor
    实现的定时任务)→
    references/cron.md
  • 作业(通过
    AppJobRoom
    +
    useJobs
    实现的持久化后台任务——任何需要独立于HTTP响应运行的任务:AI生成、导出、渲染)→
    references/jobs.md
  • 支付(Stripe支持的订阅、付费墙、一次性产品、打赏、退款、取消——请勿自行实现Stripe逻辑;使用
    useSubscription
    /
    useCheckout
    /
    requireSubscription
    )→
    references/payments.md
  • 游戏房间(回合/ tick游戏循环、大厅、主机进阶阶段、
    useGameRoom
    +
    GameRoom
    DO)→
    references/sdk-reference.md
    § 实时协作 + § 游戏房间
  • 自定义绑定与计量(Vectorize、AI、R2、KV、D1、Queues、Hyperdrive;
    "auto"
    自动配置;D1的
    runMigrations
    ;通过自动附加的
    USAGE_EVENTS
    AE数据集实现的按租户
    meterAi
    /
    meterVectorize
    汇总)→
    references/bindings.md
如果应用仅需要客户端钩子和
integration.post(...)
,可跳过所有上述扩展。

Integrations

集成功能

Call external APIs through the api-worker proxy:
typescript
import { integration } from 'deepspace'
const result = await integration.post('openweathermap/geocoding', { q: city })
// Returns: { success: true, data: <endpoint-specific> } | { success: false, error: string }
Endpoint names are two segments:
<integration>/<endpoint>
.
Don't guess — names like
geocode-city
or
weather-forecast
aren't real and return 404 at runtime. Verify with
npx deepspace integrations list
/
info <ep>
(the agent-friendly catalog + schema source — no auth, no app dir required).
Default billing is owner-pays, so auth-gate any UI that calls
integration.post(...)
to keep anonymous bots from billing the owner. →
references/integrations.md
for billing modes, the discovery CLI, testing rules, and the response-envelope gotchas.
通过api-worker代理调用外部API:
typescript
import { integration } from 'deepspace'
const result = await integration.post('openweathermap/geocoding', { q: city })
// Returns: { success: true, data: <endpoint-specific> } | { success: false, error: string }
端点名称由两部分组成:
<integration>/<endpoint>
。请勿猜测——类似
geocode-city
weather-forecast
的名称不存在,运行时会返回404。请使用
npx deepspace integrations list
/
info <ep>
验证(这是适合代理的目录+Schema来源——无需认证、无需应用目录)。
默认计费方式为所有者付费,因此请为所有调用
integration.post(...)
的UI添加认证限制
,防止匿名机器人产生费用。→
references/integrations.md
了解计费模式、发现CLI、测试规则和响应信封注意事项。

Login, test, deploy

登录、测试、部署

Login (
npx deepspace login
)

登录(
npx deepspace login

npx deepspace whoami
is the canonical login-state probe (add
--json
from agents). It refreshes the JWT in the same call path that
dev
/
test
/
deploy
use — if
whoami
succeeds, those will too. On failure: stderr
Not logged in
. Run `deepspace login`.`, exit 1.
dev
/
test
/
deploy
themselves require a valid session at
~/.deepspace/session
; if absent, they exit with
Not logged in
. Run `deepspace login` first.` Four hard rules:
  1. Pause and tell the user. Login opens a browser tab (GitHub/Google OAuth) on their machine and polls up to 10 minutes. They need to be at the keyboard. There is no agent-runnable bypass — never ask the user for their password.
  2. Run interactive login without an artificial time bound. Do not wrap in
    timeout N
    ,
    sleep N && kill
    , or any cutoff — those terminate OAuth before completion and leave no session. (
    timeout
    isn't installed on macOS by default; don't reach for it.) Run in foreground or a true background process.
  3. After login completes, verify with
    npx deepspace whoami
    before retrying
    dev
    /
    test
    /
    deploy
    . Re-running them while login is still polling produces the same error — that's expected order, not a bug.
  4. Never copy
    .dev.vars
    from a sibling app.
    APP_OWNER_JWT
    is minted against that app's wrangler name; borrowing causes silent auth mismatches.
**
npx deepspace whoami
**是检查登录状态的标准方式(代理可添加
--json
参数)。它会刷新JWT,与
dev
/
test
/
deploy
使用的调用路径相同——如果
whoami
成功,那么这些操作也会成功。失败时:标准错误输出
Not logged in
. Run `deepspace login`.,退出码1。
dev
/
test
/
deploy
本身需要
~/.deepspace/session
中的有效会话;如果不存在,会输出
Not logged in
. Run `deepspace login` first.并退出。请遵守以下四条硬性规则:
  1. 暂停操作并告知用户。登录会在用户的机器上打开一个浏览器标签页(GitHub/Google OAuth),并最多轮询10分钟。用户需要在键盘前完成操作。没有代理可绕过的方式——永远不要向用户索要密码。
  2. 运行交互式登录时不要设置人为时间限制请勿使用
    timeout N
    sleep N && kill
    或任何截断操作——这些会在OAuth完成前终止进程,导致无法生成会话。(macOS默认未安装
    timeout
    ;请勿使用它。)请在前台或真正的后台进程中运行登录命令。
  3. 登录完成后,使用
    npx deepspace whoami
    验证
    ,然后再重试
    dev
    /
    test
    /
    deploy
    。在登录仍在轮询时重新运行这些操作会产生相同的错误——这是正常的顺序,不是bug。
  4. 永远不要从其他应用复制
    .dev.vars
    文件
    APP_OWNER_JWT
    是针对该应用的wrangler名称生成的;借用会导致静默的认证不匹配。

Test (
npx deepspace test
)

测试(
npx deepspace test

Tests are the primary way to verify code changes. The scaffolded specs (
smoke.spec.ts
/
api.spec.ts
/
collab.spec.ts
) are starting points — extend them per the Step 8 checklist in
references/testing.md
. The full extension table, debug-from-failures rule, route coverage, multi-user patterns, and the
'deepspace/testing'
fixture all live in that file.
One rule stays here because it bites first-time runs: run tests only after a runtime-affecting code change (
src/
,
worker.ts
, etc.). Skip them for conversation, planning, reading, or pure documentation edits — don't run as a ritual.
测试是验证代码变更的主要方式。脚手架提供的测试用例(
smoke.spec.ts
/
api.spec.ts
/
collab.spec.ts
)是起点——请根据
references/testing.md
中的步骤8检查清单扩展它们。完整的扩展表、从失败中调试的规则、路由覆盖率、多用户模式以及
'deepspace/testing'
夹具都在该文档中。
有一条规则需要在此强调,因为它会影响首次运行:仅在代码变更影响运行时(
src/
worker.ts
等)后才运行测试。在讨论、规划、阅读或纯文档编辑时,请跳过测试——不要将其作为例行操作。

Deploy (
npx deepspace deploy
)

部署(
npx deepspace deploy

On an initial build, run the pre-deploy checklist in
references/uiux.md
§5 first. On follow-up deploys with those already verified, just run the command:
bash
npx deepspace deploy   # → <wrangler.name>.app.space
The subdomain is the
name
field in
wrangler.toml
. Edit it there if you want a different deploy target —
deploy
does not accept a name override. Re-run
npx deepspace login
if the session has expired.
首次构建时,请先执行
references/uiux.md
§5中的部署前检查清单。后续部署时,如果已完成这些检查,只需运行命令即可:
bash
npx deepspace deploy   # → <wrangler.name>.app.space
子域名由
wrangler.toml
中的
name
字段决定。如果需要不同的部署目标,请在此处编辑该字段——
deploy
不接受名称覆盖。如果会话过期,请重新运行
npx deepspace login

.dev.vars
contract

.dev.vars
约定

dev
/
test
rewrite only the 9 SDK-managed keys:
AUTH_JWT_PUBLIC_KEY
,
AUTH_JWT_ISSUER
,
AUTH_WORKER_URL
,
API_WORKER_URL
,
PLATFORM_WORKER_URL
,
OWNER_USER_ID
,
APP_OWNER_JWT
,
APP_IDENTITY_TOKEN
,
ALLOW_DEBUG_ROUTES
. They live above a
# --- not managed by the SDK; preserved across dev/test runs ---
divider the CLI writes itself.
APP_IDENTITY_TOKEN
is only populated after the first
npx deepspace deploy
(deploy-worker mints it on app registration) — fine for most apps; only matters if you're using payments or
captureScreenshot
locally before deploy. See
references/payments.md
/
references/sdk-reference.md
.
Anything you add below that divider — third-party API tokens, custom feature flags, your own service URLs — is preserved verbatim across
dev
/
test
runs, and shipped to prod as
secret_text
bindings on
deploy
(same
env.MY_KEY
access pattern in dev and prod; no
wrangler secret put
step).
Limits enforced server-side at deploy:
  • Name must match
    ^[A-Za-z_][A-Za-z0-9_]*$
    .
  • Per-value cap: 32 KB (32 × 1024 bytes).
  • Total cap across all user secrets: 128 KB.
  • Raw JSON payload cap: 1 MB → 413.
  • Name must not collide with
    RESERVED_BINDING_NAMES
    (11 SDK-owned), any declared custom binding, or any DO class in
    __DO_MANIFEST__
    .
Read
references/bindings.md
if any of those collisions trip you.
dev
/
test
仅重写9个SDK管理密钥
AUTH_JWT_PUBLIC_KEY
AUTH_JWT_ISSUER
AUTH_WORKER_URL
API_WORKER_URL
PLATFORM_WORKER_URL
OWNER_USER_ID
APP_OWNER_JWT
APP_IDENTITY_TOKEN
ALLOW_DEBUG_ROUTES
。这些密钥位于CLI自动写入的
# --- not managed by the SDK; preserved across dev/test runs ---
分隔符上方。
APP_IDENTITY_TOKEN
仅在首次执行
npx deepspace deploy
后才会填充(部署Worker会在应用注册时生成它)——对大多数应用来说没问题;仅当在部署前本地使用支付或
captureScreenshot
时才需要它。详见
references/payments.md
/
references/sdk-reference.md
您在分隔符下方添加的任何内容——第三方API令牌、自定义功能标志、您自己的服务URL——都会在
dev
/
test
运行过程中完整保留,并在
deploy
时作为
secret_text
绑定部署到生产环境
(开发和生产环境中均通过
env.MY_KEY
访问;无需执行
wrangler secret put
步骤)。
部署时服务器端会强制执行以下限制:
  • 名称必须匹配
    ^[A-Za-z_][A-Za-z0-9_]*$
  • 单个值上限:32 KB(32 × 1024字节)。
  • 所有用户密钥的总上限:128 KB
  • 原始JSON负载上限:1 MB → 返回413错误。
  • 名称不得与
    RESERVED_BINDING_NAMES
    (11个SDK自有名称)、任何已声明的自定义绑定或
    __DO_MANIFEST__
    中的任何DO类冲突。
如果遇到上述冲突,请阅读
references/bindings.md

Handling rules —
.dev.vars
holds live credentials

处理规则——
.dev.vars
包含实时凭证

The file holds a live
APP_OWNER_JWT
(signed against the user's identity) plus whatever third-party tokens (Stripe, OpenAI, …) the user wrote below the divider. Treat its contents as secret throughout the session, not just at commit time:
  • Never read the file's values into your output. No
    cat .dev.vars
    , no
    head
    /
    grep
    /
    Read
    -then-paste-into-chat, no inclusion in summaries, generated docs, READMEs, commit messages, PR bodies, or screenshots. If you need to confirm a key is present, check the key name (
    grep -l '^STRIPE_SECRET_KEY=' .dev.vars
    — files-only, not content) and report presence/absence — never the value.
  • Never pass secrets as CLI args.
    MY_KEY=… npx deepspace dev
    leaks into shell history,
    ps aux
    , and child-process env dumps. Write the line into
    .dev.vars
    below the divider and let the SDK pick it up via
    env.MY_KEY
    in worker code.
  • Never commit
    .dev.vars
    .
    The scaffold's
    .gitignore
    covers it; do not add a
    !
    exception, do not
    git add -f .dev.vars
    , do not paste its contents into a tracked file "for clarity." If a
    git status
    shows it untracked, that's the correct state — leave it.
  • Never assert on secret values in tests. Test that auth works (a request returns 200, a webhook fires) — never
    expect(env.STRIPE_SECRET_KEY).toBe('sk_live_…')
    and never echo the value into a request body that goes to a third party you don't control.
  • Adding a new secret is one step: append
    KEY=value
    below the divider in
    .dev.vars
    , then
    npx deepspace dev
    /
    deploy
    . The CLI handles upload as
    secret_text
    on deploy — no
    wrangler secret put
    , no out-of-band copy.
该文件包含有效的
APP_OWNER_JWT
(针对用户身份签名)以及用户在分隔符下方添加的任何第三方令牌(Stripe、OpenAI等)。在整个会话过程中,请将其内容视为机密,而不仅仅是在提交时:
  • 永远不要将文件内容读取到输出中。不要执行
    cat .dev.vars
    head
    /
    grep
    /
    Read
    后粘贴到聊天中,不要包含在摘要、生成的文档、README、提交消息、PR正文或截图中。如果需要确认某个密钥是否存在,请检查密钥名称
    grep -l '^STRIPE_SECRET_KEY=' .dev.vars
    ——仅检查文件是否包含该密钥,不显示内容)并报告存在/不存在——永远不要显示值。
  • 永远不要将机密作为CLI参数传递
    MY_KEY=… npx deepspace dev
    会泄露到shell历史、
    ps aux
    和子进程环境转储中。请将该行添加到
    .dev.vars
    的分隔符下方,让SDK在Worker代码中通过
    env.MY_KEY
    获取。
  • 永远不要提交
    .dev.vars
    。脚手架的
    .gitignore
    已包含该文件;请勿添加
    !
    例外,不要执行
    git add -f .dev.vars
    ,不要将其内容粘贴到跟踪文件中“以便清晰查看”。如果
    git status
    显示它未被跟踪,这是正确的状态——请保持不变。
  • 永远不要在测试中断言机密值。测试认证是否有效(请求返回200、webhook触发)——不要执行
    expect(env.STRIPE_SECRET_KEY).toBe('sk_live_…')
    ,永远不要将值回显到发送给不受您控制的第三方的请求体中。
  • 添加新机密只需一步:在
    .dev.vars
    的分隔符下方追加
    KEY=value
    ,然后执行
    npx deepspace dev
    /
    deploy
    。CLI会在部署时将其作为
    secret_text
    上传——无需执行
    wrangler secret put
    ,无需手动复制。

References

参考文档

Required preflight before any code change. Before editing files or writing code:
  1. List the files you will touch.
  2. Scan the table below and list every row whose "Read before" trigger matches the work.
  3. Read
    each matching reference in this turn, before the first edit — not after, not "if needed later."
  4. If your list under (2) is empty, stop and re-scan the table; for any non-trivial DeepSpace work at least one row applies.
Each reference also declares its own "Load when …" trigger as its first line — that gate is authoritative; if it says load, load it before touching the matching surface.
ReferenceRead before
references/sdk-reference.md
Reaching for any hook, type, or export beyond
useQuery
/
useMutations
/
useAuth
. Especially required for multiplayer / game rooms, presence, Yjs, canvas, R2, messaging. Open this before
node_modules/deepspace/dist/*.d.ts
.
references/schemas.md
Defining a collection, picking a permission rule, debugging "why can't this user see/edit X," wiring
visibilityField
/
collaboratorsField
.
references/auth.md
Choosing the auth model (public / gated / mixed), adding
<AuthGate>
, customizing the sign-in fallback.
references/architecture.md
Editing
worker.ts
, adding cross-app shared scopes (
workspace:*
/
dir:*
/
conv:*
), wiring
platformWorkerFetch
, understanding the WebSocket /
/api/*
identity-strip security model.
references/server-actions.md
Adding privileged writes that bypass the caller's RBAC.
references/ai-chat.md
Adding a streamed chat UI with tool use over the app's records.
references/cron.md
Adding scheduled tasks, building the admin cron monitor, testing cron via
trigger
.
references/jobs.md
Adding background-job handlers (AI generation, exports, renders), choosing client vs server enqueue, handling progress / cancellation / multi-tick checkpoints.
references/bindings.md
Declaring custom Cloudflare bindings (Vectorize / R2 / KV / D1 / Queues / AI / Browser / Hyperdrive / AE),
"auto"
autoprovisioning, D1 bootstrap with
runMigrations
, per-tenant cost rollup via
meterAi
/
meterVectorize
/
meterUsage
.
references/integrations.md
Calling external APIs (LLMs, search, media, social, finance, etc.).
references/payments.md
Anything involving money, Stripe, billing, paywalls, subscriptions, pricing pages, "Upgrade" buttons, Pro / premium tiers, gating features behind a plan, one-time products, tips, donations, free trials, refunds, or cancellation. Never hand-roll Stripe in a DeepSpace app — declare in
src/subscriptions.ts
/
src/products.ts
and use
useSubscription
/
useCheckout
/
requireSubscription
.
references/domain.md
Buying / attaching / managing a custom domain (
deepspace domain
CLI). Skip for apps that are happy on
<name>.app.space
.
references/integrations/livekit.md
Adding audio/video rooms — token mint, billing model, room lifecycle.
references/integrations/google-oauth.md
Calling Gmail / Calendar / Drive / Contacts — per-user billing, scope step-up,
requiresOAuth
retry, Playwright
page.route()
mocks.
references/uiux.md
Working on theme, home page, primitives, interaction polish, or "feels generic" feedback. Trigger especially when about to use
<select>
/
window.confirm
/
window.alert
/
window.prompt
.
references/testing.md
Writing or extending specs, applying the Step 8 checklist, building multi-user flows, route coverage, debugging flaky tests.
references/landing-design.md
Building marketing / landing / splash pages, addressing "feels AI-generated" feedback, customizing the scaffolded
landing
feature.
任何代码变更前必须执行的预检步骤。在编辑文件或编写代码前:
  1. 列出您将修改的文件。
  2. 扫描下表,列出所有“阅读时机”与您的工作匹配的行。
  3. 在本次会话中阅读每个匹配的参考文档,在首次编辑前完成——不要在编辑后阅读,也不要“以后需要时再读”。
  4. 如果步骤2中的列表为空,请停止并重新扫描表格;任何非 trivial 的DeepSpace工作至少会匹配一行。
每个参考文档的第一行也声明了自己的“加载时机”触发条件——该条件是权威的;如果它说需要加载,请在接触对应的功能前加载该文档。
参考文档阅读时机
references/sdk-reference.md
当您需要使用
useQuery
/
useMutations
/
useAuth
之外的任何钩子、类型或导出时。尤其是多玩家/游戏房间、在线状态、Yjs、画布、R2、消息功能。在查看
node_modules/deepspace/dist/*.d.ts
前,请先阅读此文档。
references/schemas.md
定义集合、选择权限规则、调试“为什么该用户无法查看/编辑X”、配置
visibilityField
/
collaboratorsField
时。
references/auth.md
选择认证模型(公开 / gated / 混合)、添加
<AuthGate>
、自定义登录回退逻辑时。
references/architecture.md
编辑
worker.ts
、添加跨应用共享范围(
workspace:*
/
dir:*
/
conv:*
)、配置
platformWorkerFetch
、理解WebSocket /
/api/*
的身份剥离安全模型时。
references/server-actions.md
添加绕过调用者RBAC的特权写入时。
references/ai-chat.md
添加支持工具调用的流式聊天UI以操作应用记录时。
references/cron.md
添加定时任务、构建管理员定时任务监控、通过
trigger
测试定时任务时。
references/jobs.md
添加后台任务处理器(AI生成、导出、渲染)、选择客户端 vs 服务器入队、处理进度/取消/多tick检查点时。
references/bindings.md
声明自定义Cloudflare绑定(Vectorize / R2 / KV / D1 / Queues / AI / Browser / Hyperdrive / AE)、
"auto"
自动配置、使用
runMigrations
初始化D1、通过
meterAi
/
meterVectorize
/
meterUsage
实现按租户成本汇总时。
references/integrations.md
调用外部API(LLM、搜索、媒体、社交、金融等)时。
references/payments.md
涉及资金、Stripe、计费、付费墙、订阅、定价页面、“升级”按钮、专业/高级套餐、功能按计划限制、一次性产品、打赏、捐赠、免费试用、退款或取消的任何场景。永远不要在DeepSpace应用中自行实现Stripe逻辑——在
src/subscriptions.ts
/
src/products.ts
中声明,并使用
useSubscription
/
useCheckout
/
requireSubscription
references/domain.md
购买/绑定/管理自定义域名(
deepspace domain
CLI)。如果应用使用
<name>.app.space
即可满足需求,可跳过此文档。
references/integrations/livekit.md
添加音视频房间——令牌生成、计费模型、房间生命周期时。
references/integrations/google-oauth.md
调用Gmail / Calendar / Drive / Contacts——按用户计费、范围提升、
requiresOAuth
重试、Playwright
page.route()
模拟时。
references/uiux.md
处理主题、首页、组件、交互优化或“感觉通用”的反馈时。尤其是当您打算使用
<select>
/
window.confirm
/
window.alert
/
window.prompt
时。
references/testing.md
编写或扩展测试用例、应用步骤8检查清单、构建多用户流程、路由覆盖率、调试不稳定测试时。
references/landing-design.md
构建营销/着陆/启动页面、处理“感觉是AI生成的”反馈、自定义脚手架提供的
landing
功能时。

Gotchas

常见陷阱

Cross-cutting traps that don't have a natural reference home. Domain-specific gotchas live in their topical reference (auth, schemas, integrations, architecture, testing, bindings).
  • Scaffold's local UI primitives shadow the SDK
    _app.tsx
    wraps the tree in
    ToastProvider
    from
    src/components/ui/
    , not from
    deepspace
    . Importing
    useToast
    (or any locally-shadowed primitive) from
    deepspace
    throws
    useToast must be used within ToastProvider
    at runtime — the React contexts don't match. Import from
    ../components/ui
    , not from
    deepspace
    .
    Full explanation in
    references/uiux.md
    § "Critical import rule."
  • Page files belong in
    src/pages/
    — generouted scans only this directory. Putting pages in
    src/features/<name>/
    results in 404s even if nav links exist.
  • Don't scaffold-then-move to pair a directory with a different subdomain. If you need directory
    foo-site
    with subdomain
    foo-main
    , scaffold into
    foo-site
    and edit
    wrangler.toml
    's
    name
    to
    foo-main
    . Scaffolding as
    foo-main
    then moving the files lands in the same state with extra failure surface (broken
    git init
    , stray
    .wrangler/
    paths). See
    references/architecture.md
    § App-name rules.
  • Never put identity in WebSocket URLs or
    /api/*
    headers.
    The starter
    wsRoute
    strips
    userId
    /
    userName
    /
    userEmail
    /
    userImageUrl
    /
    role
    query params on every upgrade and re-applies them only from a verified JWT. The platform worker does the same on
    /api/*
    (overwrites
    X-User-Id
    from JWT, strips
    X-App-Action
    ). Caller identity is always the JWT subject — there is no client-side override. Three valid WS states: no token → anonymous (DO assigns
    anon-<uuid>
    ); invalid token → 401; valid token → JWT identity. (Cross-app scopes
    workspace:*
    /
    dir:*
    /
    conv:*
    have no anonymous path — auth is required.)
  • Port 5173 may be held by a parallel session
    tests/playwright.config.ts
    ships with
    reuseExistingServer: true
    , so a sibling session's Vite on 5173 is picked up and your tests run against its app. Do not kill a parallel session's processes. For your own leaked workerd/wrangler (crashed terminal, IDE close), use
    npx deepspace kill
    (add
    --all
    to sweep every workerd/wrangler/vite on the box). For genuine parallel work, use
    --port 5174
    (or 5175, 5176, …) and edit
    tests/playwright.config.ts
    so
    webServer.port
    and
    use.baseURL
    both match before running tests.
这些跨领域的陷阱没有合适的参考文档归属。特定领域的陷阱请查看对应的参考文档(认证、Schema、集成、架构、测试、绑定)。
  • 脚手架的本地UI组件会覆盖SDK组件——
    _app.tsx
    使用
    src/components/ui/
    中的
    ToastProvider
    包裹整个组件树,而非
    deepspace
    中的。从
    deepspace
    导入
    useToast
    (或任何被本地覆盖的组件)会在运行时抛出
    useToast must be used within ToastProvider
    错误——React上下文不匹配。请从
    ../components/ui
    导入,不要从
    deepspace
    导入
    。完整说明请查看
    references/uiux.md
    § “关键导入规则”。
  • 页面文件必须放在
    src/pages/
    目录下
    ——generouted仅扫描此目录。将页面放在
    src/features/<name>/
    目录下会导致404错误,即使存在导航链接。
  • 不要先搭建脚手架再移动目录以匹配不同的子域名。如果需要目录
    foo-site
    对应子域名
    foo-main
    ,请直接在
    foo-site
    目录下搭建脚手架,然后编辑
    wrangler.toml
    name
    字段为
    foo-main
    。先以
    foo-main
    搭建脚手架再移动文件会导致额外的失败风险(
    git init
    损坏、
    .wrangler/
    路径错误)。详见
    references/architecture.md
    § 应用名称规则。
  • 永远不要在WebSocket URL或
    /api/*
    头中包含身份信息
    。初始的
    wsRoute
    会在每次升级时剥离
    userId
    /
    userName
    /
    userEmail
    /
    userImageUrl
    /
    role
    查询参数,仅从验证后的JWT重新应用这些信息。平台Worker在
    /api/*
    请求上也会执行相同操作(从JWT覆盖
    X-User-Id
    ,剥离
    X-App-Action
    )。调用者身份始终是JWT的主体——没有客户端覆盖的方式。WebSocket有三种有效状态:无令牌→匿名(DO分配
    anon-<uuid>
    );无效令牌→401;有效令牌→JWT身份。(跨应用范围
    workspace:*
    /
    dir:*
    /
    conv:*
    不支持匿名路径——必须认证。)
  • 端口5173可能被并行会话占用——
    tests/playwright.config.ts
    默认配置
    reuseExistingServer: true
    ,因此并行会话中运行在5173端口的Vite会被复用,您的测试会针对应用运行。不要终止并行会话的进程。对于您自己的泄露进程(终端崩溃、IDE关闭),请使用
    npx deepspace kill
    (添加
    --all
    可清除机器上所有的workerd/wrangler/vite进程)。如果需要真正的并行工作,请使用
    --port 5174
    (或5175、5176等),并在运行测试前编辑
    tests/playwright.config.ts
    ,使
    webServer.port
    use.baseURL
    匹配该端口。