15 KiB
15 KiB
NomadCNA — Cursor 项目上下文报告
生成日期:2026-06-07
用途:为 Cursor AI 助手提供项目全貌、架构约定与开发指引。
生产站点:https://nomadro.cn
1. 项目简介
NomadCNA(游牧中国) 是面向数字游民的生活操作系统,单仓 Monorepo 包含:
- 主站:城市探索、下一站决策、活动、社区、支付、统计等
- Digital 子站(
/digital):指南、课程、电子书、远程工作、个人资料 - FastAPI 后端:认证、业务 API、支付回调、PocketBase 集成
- 外部服务:PocketBase、MinIO、MiroTalk P2P、The Lounge + Ergo IRC
| 模块 | 说明 |
|---|---|
| 城市探索 | 18 城静态数据 + API,生活成本/网速/安全等指标 |
| 下一站决策 | /dashboard,预算/气候/标签推荐 |
| 活动 | 线上/线下/混合,MiroTalk 视频 + Web 群聊 |
| 社区 | 交友匹配、讨论、任务赏金、反馈 |
| 会员与支付 | ZPay / XorPay,加入表单 + VIP 状态 |
| Digital 子站 | 课程章节、电子书 Markdown、资源导航 |
| 媒体 | MinIO 上传 + 远程媒体代理缓存 |
2. 技术栈
| 层级 | 技术 | 版本 |
|---|---|---|
| 前端框架 | Next.js App Router | 16.1.6 |
| UI | React + TypeScript | 19.2.3 / TS 5 |
| 样式 | Tailwind CSS | 4 |
| 图表 | ECharts | 6 |
| Markdown | marked, react-markdown, highlight.js | — |
| 后端 | FastAPI + uvicorn | ≥0.115 |
| 数据库 | PocketBase | SDK 0.27 |
| 对象存储 | MinIO | Node + Python SDK |
| 支付 | ZPay / XorPay 适配层 | — |
| 包管理 | pnpm | 10.25.0 |
| Node 生产版本 | — | v22.13.1 |
路径别名:@/* → 项目根目录(见 tsconfig.json)。
3. 架构总览
flowchart TB
subgraph Client["浏览器"]
Next["Next.js 16<br/>:3001 dev / :4002 prod"]
end
subgraph APIs["API 层"]
NextAPI["Next Route Handlers<br/>/api/digital/*<br/>/api/media/*"]
FastAPI["FastAPI<br/>:8000<br/>/api/*"]
end
subgraph Data["数据与服务"]
PB["PocketBase :8090"]
MinIO["MinIO :9100"]
MiroTalk["MiroTalk P2P :9300"]
Lounge["The Lounge :9000"]
Ergo["Ergo IRC :6667"]
end
Client --> Next
Next -->|"rewrite 排除 digital/media"| FastAPI
Next --> NextAPI
NextAPI --> PB
NextAPI --> MinIO
FastAPI --> PB
FastAPI --> MinIO
Next --> MiroTalk
Next --> Lounge
Lounge --> Ergo
API 路由分流(关键)
next.config.ts 将 除 digital 和 media 外 的所有 /api/* 转发到 FastAPI:
source: "/api/:path((?!(?:digital|media)(?:$|/.*)).*)"
destination: "http://127.0.0.1:8000/api/:path*"
| 路径前缀 | 处理方 |
|---|---|
/api/digital/* |
Next.js Route Handlers |
/api/media/* |
Next.js Route Handlers |
其他 /api/* |
FastAPI(经 rewrite 代理) |
前端统一通过 app/lib/api-client.ts 的 apiFetch() / apiUrl() 调用后端。
4. 目录结构
.
├── app/
│ ├── [locale]/ # 主站多语言页面(49 个 page.tsx)
│ │ └── digital/ # Digital 子站页面路由
│ ├── api/
│ │ ├── digital/ # Digital 认证、支付、上传、VIP(13 个 route)
│ │ └── media/proxy/ # 远程媒体代理
│ ├── components/ # 主站通用组件(Navbar、Hero、AuthModal 等)
│ ├── context/ # LocaleContext、ThemeContext
│ ├── data/ # cities.ts、map-cities.ts、mock.ts
│ ├── digital/ # Digital 子站组件、lib、context(与主站平行)
│ └── lib/ # api-client、payment、meetups、pocketbase、charts
├── backend/
│ ├── main.py # FastAPI 入口(~50 个端点)
│ ├── settings.py # 环境变量
│ ├── pb_client.py # PocketBase HTTP 客户端
│ ├── payment.py # ZPay / XorPay
│ └── minio_storage.py # MinIO 上传
├── config/
│ ├── site.config.ts # 主站 SEO
│ ├── nav.config.ts # 顶部导航
│ ├── home.config.ts # 首页静态内容
│ ├── services.config.ts # 主站服务配置
│ └── digital/ # Digital 子站专属配置
├── i18n/
│ ├── routing.ts # locales: zh/en, default: zh
│ └── navigation.ts # 语言感知 Link/Router 导出
├── messages/ # zh.json、en.json 主站文案
├── content/digital/ # Digital 主题数据(tools.json 等)
├── public/ # 静态资源
├── next.config.ts
├── package.json
└── pnpm-workspace.yaml
主站 vs Digital 子站代码边界
| 区域 | 路径 | 说明 |
|---|---|---|
| 主站页面 | app/[locale]/* |
城市、活动、社区等 |
| 主站组件 | app/components/ |
Navbar、Sidebar、CityCard 等 |
| 主站工具 | app/lib/ |
api-client、meetups、payment |
| Digital 页面 | app/[locale]/digital/* |
课程、电子书、工作等 |
| Digital 组件 | app/digital/components/ |
独立 Header、Hero、课程区块 |
| Digital 工具 | app/digital/lib/ |
平行的 payment、pocketbase、learning |
| Digital 配置 | config/digital/* |
课程、域名、视觉主题 |
两套代码存在 有意平行(非完全共享),修改时注意对应目录。
5. 路由与国际化
- 语言:
zh(默认)、en,路由 始终带前缀(/zh/...、/en/...) - 配置:
i18n/routing.ts - 文案:
messages/zh.json、messages/en.json;Digital 另有content/digital/themes/.../messages/ - 运行时 i18n:
LocaleContext+t("key.path")点分键 - 语言感知导航:必须使用
i18n/navigation.ts导出的Link、useRouter
// ✅ 正确
import { Link, useRouter, useTranslation } from "@/i18n/navigation";
// ❌ 避免直接用 next/link(会丢失 locale 前缀)
import Link from "next/link";
新页面流程:
- 在
app/[locale]/下创建page.tsx - 在
messages/zh.json和messages/en.json补充文案键 - 如需导航入口,更新
config/nav.config.ts
6. API 端点速查
6.1 Next.js Route Handlers(app/api/digital/)
| 路径 | 作用 |
|---|---|
auth/login、register、logout、me、sync-session |
Digital 认证 |
join |
加入申请表单 → PocketBase |
pay、pay/status、pay/confirm |
Digital 支付 |
vip/check |
VIP 状态 |
upload-media |
媒体上传 MinIO |
jobs |
远程工作列表 |
media/proxy |
远程媒体抓取缓存 |
6.2 FastAPI(backend/main.py)
| 分类 | 端点示例 |
|---|---|
| 健康 | GET /api/health |
| 认证 | POST /api/auth/email、/google、GET /api/auth/me |
| 加入/支付 | POST /api/join、/api/pay、GET /api/pay/status |
| 城市/内容 | GET /api/cities、/api/content/home、POST /api/content/submissions |
| 活动 | GET/POST /api/meetups |
| 社区 | GET/POST /api/discussions、/api/gigs、/api/profiles、/api/matches/swipes |
| 通知 | GET/POST /api/notifications/* |
| 统计 | GET /api/stats/member-map、/overview、/city-ranking |
| 推荐 | POST /api/recommendations/next-stop |
| 其他 | POST /api/feedback、POST /api/ai/assistant(占位) |
| 支付回调 | /cnomadcna/zpay_order_status、/cnomadcna/xorpay_notify |
7. 核心业务模块指引
7.1 城市探索
- 静态数据:
app/data/cities.ts(18 城) - 首页:
app/[locale]/page.tsx+FilterBar、CityCard、CityModal - 详情:
app/[locale]/city/[slug]/page.tsx - API 补充:
GET /api/cities、/api/cities/{slug}
7.2 活动 / 视频 / 群聊
- 页面:
app/[locale]/meetups/、meetups/host/ - 核心逻辑:
app/lib/meetups.ts- MiroTalk 房间 slug 生成:
createMiroTalkRoomSlug() - 默认视频地址:
NEXT_PUBLIC_MIROTALK_URL - 默认群聊地址:
NEXT_PUBLIC_LOUNGE_URL
- MiroTalk 房间 slug 生成:
- 线上/混合活动展示 MiroTalk iframe + The Lounge 入口
7.3 支付
- 前端:
app/lib/payment/(client、config、usePayStatusPoll) - Digital 平行:
app/digital/lib/payment/ - 后端:
backend/payment.py(ZPayProvider、XorPayProvider) - 配置:
config/services.config.ts、config/digital/services.config.ts
7.4 认证
- 主站 Cookie:
app/lib/auth-cookie.ts - PocketBase 封装:
app/lib/pocketbase/auth.ts - FastAPI 会话:
backend/pb_client.py
7.5 图表与年报
app/lib/charts/:ECharts 封装(ReportChart、MembersMap)- 页面:
app/[locale]/report/、report/data/
8. 配置系统
| 文件 | 用途 |
|---|---|
config/site.config.ts |
主站标题、描述、SEO |
config/nav.config.ts |
顶部导航链接 |
config/home.config.ts |
首页成员头像、路线、统计 |
config/footer.config.ts |
页脚链接 |
config/filter.config.ts |
城市筛选选项 |
config/services.config.ts |
主站 PocketBase/支付/MinIO |
config/runtime-env.ts |
APP_ENV 运行时判断 |
config/digital/site.config.ts |
Digital 功能开关、主题 |
config/digital/course.ts |
课程模块数据 |
config/digital/lessons.ts |
课程章节内容 |
config/digital/domain.config.ts |
域名与服务地址推导 |
环境判断:IS_DEVELOPMENT / IS_PRODUCTION 来自 config/runtime-env.ts。
9. 开发命令
# 安装
pnpm install
# 前端开发(端口 3001,非 README 中的 3000)
pnpm dev
# 后端开发
python3 -m venv backend/.venv
# Windows: backend\.venv\Scripts\activate
pip install -r backend/requirements.txt
uvicorn backend.main:app --host 127.0.0.1 --port 8000 --reload
# 质量检查
pnpm lint
pnpm exec tsc --noEmit --pretty false
# 生产构建
APP_ENV=production NEXT_PUBLIC_APP_ENV=production NODE_ENV=production pnpm build
pnpm start
本地需同时运行 Next.js (:3001) 和 FastAPI (:8000) 才能完整调试 API。
10. 环境变量要点
⚠️ 切勿将
.env.local、backend/.env或真实密钥提交到 Git。
.env.example中可能含示例/历史值,生产密钥应通过 systemd Environment 或服务器私密配置管理。
前端(.env.local)
| 变量 | 说明 |
|---|---|
APP_ENV / NEXT_PUBLIC_APP_ENV |
development / production |
NEXT_PUBLIC_SITE_URL |
站点根地址 |
NEXT_PUBLIC_API_BASE_URL |
API 基础路径,生产通常为 /api |
NEXT_PUBLIC_POCKETBASE_URL |
浏览器可访问的 PocketBase |
NEXT_PUBLIC_MIROTALK_URL |
MiroTalk P2P |
NEXT_PUBLIC_LOUNGE_URL |
The Lounge Web 群聊 |
NEXT_PUBLIC_MINIO_PUBLIC_URL |
MinIO 公开文件地址 |
后端(backend/.env)
| 变量 | 说明 |
|---|---|
PB_URL / POCKETBASE_URL |
PocketBase 内网地址 |
PB_ADMIN_EMAIL / PB_ADMIN_PASSWORD |
管理员凭据 |
FRONTEND_ORIGINS |
CORS 白名单 |
PAYMENT_PROVIDER |
zpay 或 xorpay |
MINIO_* |
MinIO 连接与桶配置 |
DEV_AUTO_PAY |
开发环境自动完成支付 |
11. AI 编码约定
修改代码时请遵循以下原则:
必须遵守
- 最小改动:只改与任务相关的文件,不重构无关代码
- 匹配现有风格:命名、import 路径(
@/)、组件结构与服务作者一致 - 国际化:新 UI 文案走
messages/*.json,使用t()而非硬编码中文/英文 - 路由:新页面放
app/[locale]/,链接用@/i18n/navigation的Link - API 调用:主站用
app/lib/api-client.ts的apiFetch - 配置分离:主站配置 →
config/,Digital →config/digital/ - 媒体:上传/代理优先走 MinIO 相关模块
- 支付:复用
app/lib/payment与backend/payment.py,不重复实现 - 活动:视频/群聊逻辑复用
app/lib/meetups.ts - 不提交密钥:
.env*、凭据文件永不入库
文件选择决策树
新功能属于 Digital 子站?
├── 是 → app/[locale]/digital/ + app/digital/ + config/digital/
└── 否 → app/[locale]/ + app/components/ + config/
需要新 API?
├── Digital 专属 → app/api/digital/
├── 媒体代理 → app/api/media/
└── 主站业务 → backend/main.py(FastAPI)
需要新文案?
├── 主站 → messages/zh.json + messages/en.json
└── Digital → content/digital/themes/.../messages/ 或 messages/
TypeScript 约定
strict: true,避免any- 客户端组件文件首行
"use client" - Server Component 默认,仅在需要 hooks/事件时使用 client
Python 约定
- Pydantic
BaseModel做请求体验证 - PocketBase 操作统一走
pb_client.py - 新端点加在
backend/main.py,配置放settings.py
12. 生产部署架构
| 域名 | 上游 | 服务 |
|---|---|---|
| nomadro.cn | :4002 | Next.js(cnomadcna.service) |
| api.nomadro.cn | :8000 | FastAPI |
| pocketbase.nomadro.cn | :8090 | PocketBase |
| minio.nomadro.cn | :9100/9101 | MinIO API/Console |
| mirotalk.nomadro.cn | :9300 | MiroTalk P2P |
| lounge.nomadro.cn | :9000 | The Lounge |
| ergo.nomadro.cn | HTTPS 重定向 | → lounge(IRC 仅本机 :6667) |
生产代码目录:/home/ubuntu/gitlab-instance-0a899031_cnomadcna
上线前端:
APP_ENV=production NEXT_PUBLIC_APP_ENV=production NODE_ENV=production pnpm build
systemctl restart cnomadcna.service
13. 常见陷阱
| 问题 | 说明 |
|---|---|
| dev 端口 | pnpm dev 监听 3001,不是 3000 |
| API 分流 | /api/digital/* 不走 FastAPI rewrite |
| 双套 lib | 主站 app/lib/ 与 Digital app/digital/lib/ 各自独立 |
| 静态 vs API 数据 | 城市等仍以 app/data/ 静态为主,部分模块接 FastAPI |
| Ergo 公网 | ergo.nomadro.cn 不开放 IRC 端口,仅 The Lounge 内网连接 |
| PROJECT_ANALYSIS_REPORT | 2026-06-06 报告认为旧 app/api 应逐步替换;当前仓库已并存 FastAPI + Next digital API |
| 密钥泄露 | .env.example 含历史示例值,生产必须使用独立密钥 |
14. 关键文件索引
| 场景 | 文件 |
|---|---|
| 新增主站页面 | app/[locale]/、messages/*.json |
| 新增 Digital 页面 | app/[locale]/digital/、app/digital/components/ |
| 调用后端 | app/lib/api-client.ts |
| 活动视频链接 | app/lib/meetups.ts |
| 支付流程 | app/lib/payment/、backend/payment.py |
| 主题切换 | app/context/ThemeContext.tsx |
| 导航配置 | config/nav.config.ts |
| API 代理规则 | next.config.ts |
| 后端入口 | backend/main.py |
| PocketBase 客户端 | backend/pb_client.py |
| 完整运维文档 | README.md |
| 前端专项分析 | PROJECT_ANALYSIS_REPORT.md |
15. 相关文档
README.md— 完整业务介绍、部署、服务运维、安全注意事项PROJECT_ANALYSIS_REPORT.md— 前端模块梳理与后续开发方向(2026-06-06)app/lib/charts/README.md— 图表组件使用说明.env.example/backend/.env.example— 环境变量模板
本文件供 Cursor AI 在编辑 NomadCNA 代码库时快速建立上下文。重大架构变更后请同步更新此文档。