02 · Getting Started

本地开发环境

从拿到 Mac、克隆仓库到 pnpm dev 在 3000 端口跑起来。新人按这一页一步步走,正常 30 分钟内能进生产化的开发循环。

前置依赖

5 步起项目

1

克隆 + 安装依赖

git clone <repo> softieweb
cd softieweb
nvm use 22
pnpm install

第一次 install 会比较慢(几百个包 + Capacitor 原生)。Husky 会自动装 pre-commit hook 跑 Prettier + ESLint。

2

配置环境变量

找 Gus 要 .env.local。生产 secret 走 Fly.io / GHA Secrets,本地用单独一份。最少需要:

DATABASE_URL="postgres://postgres:postgres@localhost:5432/softie"
REDIS_URL="redis://localhost:6379"
BETTER_AUTH_SECRET="..."   # openssl rand -hex 32
BETTER_AUTH_URL="http://localhost:3000"
NEXT_PUBLIC_BETTER_AUTH_URL="http://localhost:3000"

# AI(生产 key 即可,量小不会爆)
OPENROUTER_API_KEY="..."
GOOGLE_GENERATIVE_AI_API_KEY="..."

# 支付(用 sandbox 模式即可,不要用 prod key)
AIRWALLEX_CLIENT_ID="..."
AIRWALLEX_API_KEY="..."
NEXT_PUBLIC_AIRWALLEX_ENVIRONMENT="demo"

# 可选:本地不开 R2 上传也行,paywall 流程不依赖
R2_ACCOUNT_ID="..."
R2_ACCESS_KEY_ID="..."
R2_SECRET_ACCESS_KEY="..."
NEXT_PUBLIC_* 是构建时替换。改完必须重启 dev server,热重载读不到。要动态运行时读取得用 process.env[key] 字符串索引绕过 webpack。
3

起本地 DB + Redis

pnpm db:local:up   # docker compose 起 postgres + redis
pnpm db:push       # 把 schema 推到本地 DB(开发用,生产用 db:migrate)
pnpm db:seed       # 灌测试角色 + 用户

关 DB 用 pnpm db:local:down。需要图形界面看表用 pnpm db:studio

4

起 Web + Worker

# 推荐:一条命令同时起 Next.js 和 BullMQ worker
pnpm dev:all

# 或者分开起:
pnpm dev          # Next.js (Turbopack),端口 3000
pnpm dev:worker   # BullMQ worker watch 模式

不起 worker 也能登录、发消息,但主动推送、记忆抽取不会触发。

端口 3000 已经被占用很常见 —— 先 curl localhost:3000 看看是不是上次没关的进程。要查跑了什么用 lsof -i :3000
5

验证:端到端跑通

  1. 浏览器打开 http://localhost:3000
  2. 注册一个测试账号(邮箱+密码即可,不需要走 Google OAuth)
  3. /discover,点一个角色 → 进入 /new-chat/[id]
  4. 发消息,能看到 SSE 流式返回字
  5. 检查 messagesV2 表里有新行

能走完 = 环境装好。

常用命令清单

命令什么时候用
pnpm dev:all日常开发,web + worker 一起
pnpm lint提 PR 前快速验证(ESLint 足以判断能否构建)
pnpm type-checktsc --noEmit;改 schema/API 后必跑
pnpm test:unitvitest 单元测试(tests/unit/
pnpm test:integrationvitest 集成测试,连真 DB
pnpm testPlaywright e2e
pnpm test:headedPlaywright 带浏览器界面(调试用)
pnpm db:generate改了 src/lib/db/schema.ts 后生成 migration
pnpm db:migrate把生成的 SQL 应用到当前连接的 DB
pnpm db:push仅本地:直接 push schema 不生成 migration(开发快迭代)
pnpm db:studio开 Drizzle Studio 看表
pnpm cap:sync改完前端,同步到 Android 工程
pnpm cap:open:android打开 Android Studio
pnpm build完整生产构建(一般不用,CI 跑)

Android 调试要点

Capacitor 把 www.softie.ai 嵌进原生 WebView。本地调试两条路:

  1. 远程模式:直接连生产域名(默认)。改前端不需要 cap sync,但调试需要在 Chrome chrome://inspect 查 WebView。
  2. 本地模式:把 capacitor.config.tsserver.url 改成局域网 IP+3000,能调本地代码,但 Google 登录会因 origin 不匹配失败。
JDK 必须 21。如果 gradle 报 invalid source release: 21
brew install openjdk@21 && export JAVA_HOME=/opt/homebrew/opt/openjdk@21
Google 登录陷阱:Capacitor Google Auth 插件只读 clientId 字段,不是 serverClientId(虽然官方文档曾经写错过)。配错会返回 DEVELOPER_ERROR 或账号选择器立即 cancel。

调试技巧

看支付流程

本地起 sandbox,发起支付后跳 Airwallex demo 页。看 webhook 得用 ngrok 把本地暴露出去 + 在 Airwallex 控制台改 webhook URL。临时调通后记得改回去,不然测试事件会污染同事环境。

看 LLM trace

所有 LLM 调用都过 Langfuse(src/lib/langfuse.ts)。本地开发 trace 默认上报到生产 Langfuse 项目,看自己的就过滤 userId

看 SSE 流

浏览器 DevTools → Network → 类型 EventStream,能看到 token 一条条进来。worker 一侧的 Redis pub/sub 用 redis-cli SUBSCRIBE chat:* 看。

命中 NSFW 模型

主模型在 src/lib/ai-config.ts。降级模型不能比主模型贵;轻量任务(标题生成等)用 grok-4-fast。改完先跑 pnpm test:integration

分支与提交规范

OpenSpec 工作流

大改动(架构调整、契约变更、breaking change)走 OpenSpec:先读 openspec/AGENTS.md,写 spec → 评审 → 实现 → 验收。日常 bug 修复和小 feature 不需要走,直接动手。

← 上一篇
01 · 系统架构总览