# nomadro · 数字游民旅居平台 全栈数字游民旅居指南,采用 **Next.js + FastAPI + PocketBase** 架构。 品牌:**nomadro** — 用一行代码环游世界 🌏 ## 技术栈 | 层级 | 技术 | 说明 | |------|------|------| | 前端 | Next.js 16 + React 19 | SSR/ISR、组件化 UI、Turbopack | | 后端 | FastAPI | REST API、业务逻辑 | | 数据库 | PocketBase | 数据持久化、管理后台 | | 图表 | Chart.js (CDN) | 数据可视化 | | 部署 | Vercel + Railway + Docker | 前后端分离部署 | ## 项目结构 ``` nomadweb/ ├── frontend/ # Next.js 前端应用 │ ├── src/app/ # 页面路由 (App Router) │ ├── src/components/ # UI 组件 (30+) │ └── src/lib/ # API 客户端、Auth、Toast ├── backend/ # FastAPI 后端 │ ├── app/routers/ # API 路由 │ ├── app/services/ # PocketBase、Auth 服务 │ └── app/data/ # Mock 降级数据 ├── pocketbase/ # PocketBase 数据目录 ├── scripts/ # 开发启动脚本 (dev.ps1 / dev.sh) ├── docker-compose.yml # 一键启动全部服务 ├── index.html # 原始静态版(保留) └── README.md ``` ## 快速开始 ### 方式一:本地开发(推荐) **1. 启动 PocketBase(可选)** ```bash # 下载: https://pocketbase.io/docs/ # 或使用 Docker: docker run -d -p 8090:8090 -v ./pocketbase/pb_data:/pb_data ghcr.io/muchobien/pocketbase:latest ``` 访问 http://localhost:8090/_/ 创建管理员(可选,不启动则自动使用 Mock 数据)。 **2. 启动 FastAPI 后端** ```bash cd backend pip install -r requirements.txt cp .env.example .env # 按需修改 uvicorn app.main:app --reload --port 8000 ``` API 文档: http://localhost:8000/docs **3. 启动 Next.js 前端** ```bash cd frontend cp .env.local.example .env.local npm install --legacy-peer-deps npm run dev ``` 访问 http://localhost:3000 ### 方式二:一键脚本(Windows) ```powershell .\scripts\dev.ps1 ``` ### 方式三:Docker Compose ```bash docker compose up -d ``` | 服务 | 地址 | |------|------| | 前端 | http://localhost:3000 | | API | http://localhost:8000/docs | | PocketBase | http://localhost:8090/_/ | ## 功能特性 ### 首页核心板块 | 板块 | 说明 | |------|------| | 🗺️ 世界地图 | 交互式 SVG 热力图,点击查看城市详情 | | 🌍 目的地 | 筛选/搜索/排序,收藏,最多 4 城对比 | | 🎯 智能匹配 | 4 步问卷,推荐最适合的旅居城市 | | 🕐 时区看板 | 实时时钟 + 与国内团队工作时间重叠分析 | | 🗓️ 行程规划 | 多城市规划,预算汇总,分享/导入链接 | | 🧮 费用计算器 | 按目的地、住宿档次、月数估算预算 | | 💱 多币种换算 | CNY/USD/EUR/THB 等 8 种货币互转 | | 📊 就绪度测评 | 5 题评估你的数字游民准备程度 | | 💻 生活方式 | 交互式「游民一天」时间轴 | | 📋 签证指南 | 难度筛选 + 签证智能匹配向导 | | 💻 联合办公 | 精选 Co-working Space,城市/评分/网速排序 | | 🌤️ 最佳月份 | 12 月气候适宜度热力表,避开雨季 | | 🧳 行李清单 | 可勾选打包清单,localStorage 持久化 | | 🎲 命运转盘 | 随机目的地抽选,趣味决策 | | ✈️ 机票估算 | 出发城 × 季节 × 人数粗算往返票价 | | 📅 活动日历 | Meetup / 工作坊 / 线上活动 | | 📶 网速评级 | 远程办公 WiFi 评级与排行 | | 🎯 启动金目标 | 存款进度追踪,预估出发时间 | | ✨ 今日金句 | 每日游民灵感语录 | | 😴 时差估算 | 时差跨度与恢复期建议 | | 🏡 住宿指南 | Villa / Coliving / 公寓方案对比 | | 🗣️ 生存短语 | 多语言常用语一键复制 | | 💬 反馈入口 | 浮动反馈表单 | | 🏥 保险指南 | 国际医疗保险方案对比 | | 📒 支出账本 | 旅居花销分类记录与汇总 | | 📱 上网方案 | 各城 SIM / eSIM 推荐 | | 🌏 关于页 | `/about` 品牌介绍 | | 🧾 税居天数 | 183 天规则停留天数追踪 | | 🛬 到站清单 | 落地第一周按天勾选 | | ☕ 咖啡馆 | 办公友好咖啡馆推荐 | | 👋 新手引导 | 首次访问四步导览 | | 🔌 电源插座 | 插头类型 / 电压 / 适配建议 | | 🆘 紧急联系 | 急救、医院、领事馆速查 | | 📝 城市笔记 | 按城本地记录避坑与灵感 | | ⏱️ 专注时钟 | 番茄钟深度工作计时 | | 📝 博客 | 标签筛选 + 阅读进度 + 相关推荐 + 分享 | | ❓ FAQ | 搜索 + 展开/收起全部 | ### 交互与体验 - ✨ Canvas 粒子背景 + 品牌加载动画 - 🌓 深色/浅色主题切换(localStorage 持久化) - 🔍 全局搜索 `Ctrl+K`(目的地/博客/签证/FAQ) - 🧭 右侧浮动章节导航 - 📊 顶部滚动进度条 - ⚖️ 可视化城市对比(评分圆环 + 条形图) - 🔔 全局 Toast 通知 - 💡 游民小贴士浮动提示 - 🍪 Cookie 同意横幅 - ⌨️ 快捷键:`M` 智能匹配、`G` 命运转盘、`?` 帮助面板 - 📱 响应式布局,移动端适配 - 🔒 隐私政策页 `/privacy` ### 用户系统 - 🔐 登录 / 注册 / 一键演示账号 - ❤️ 收藏目的地(同步 API) - 👤 用户中心:统计、收藏、行程、成就徽章 - 演示账号:`demo@nomadro.com` / `demo123` ### 后端 API | 端点 | 方法 | 说明 | |------|------|------| | `/api/v1/destinations` | GET | 目的地列表(region/search/sort) | | `/api/v1/destinations/{slug}` | GET | 目的地详情 | | `/api/v1/destinations/compare` | POST | 城市对比(2–4 城) | | `/api/v1/calculator` | POST | 费用计算 | | `/api/v1/search` | GET | 全局搜索 | | `/api/v1/blog` | GET | 博客列表 | | `/api/v1/blog/{slug}` | GET | 博客详情 | | `/api/v1/auth/register` | POST | 注册 | | `/api/v1/auth/login` | POST | 登录 | | `/api/v1/auth/demo` | GET | 演示登录 | | `/api/v1/auth/favorites` | GET/POST | 收藏管理 | | `/api/v1/charts/*` | GET | 图表数据 | | `/api/v1/subscribe` | POST | 邮件订阅 | > PocketBase 不可用时,API 自动降级到 `backend/app/data/mock_data.py`。 ## 页面路由 | 路径 | 说明 | |------|------| | `/` | 首页(全部板块) | | `/login` | 登录 / 注册 | | `/profile` | 用户中心 | | `/destinations/[slug]` | 目的地详情(城市画像、加入行程) | | `/blog/[slug]` | 博客详情(阅读进度) | ## 环境变量 ### Backend (`backend/.env`) ```env POCKETBASE_URL=http://127.0.0.1:8090 POCKETBASE_ADMIN_EMAIL=admin@nomadro.com POCKETBASE_ADMIN_PASSWORD=admin123456 CORS_ORIGINS=http://localhost:3000 ``` ### Frontend (`frontend/.env.local`) ```env NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1 ``` ## 部署 ### 生产环境(已上线) | 项目 | 地址 | |------|------| | 网站 | https://nomadweb.nomadro.com | | API 健康检查 | https://nomadweb.nomadro.com/api/v1/health | | API 文档 | https://nomadweb.nomadro.com/docs | | Git 仓库 | https://gitea.dsx2020.com/eric/nomadweb | **服务器架构:** - 服务器:`107.173.30.245` - 反向代理:Caddy(自动 HTTPS) - 前端容器:`127.0.0.1:3055` → Next.js - 后端容器:`127.0.0.1:8055` → FastAPI - 数据库:PocketBase(Docker 内部网络) **更新部署:** ```bash # SSH 登录服务器后(当前开发分支为 dev1) cd /opt/nomadweb git fetch origin && git checkout -B dev1 origin/dev1 export DOMAIN=nomadweb.nomadro.com export NEXT_PUBLIC_API_URL=https://nomadweb.nomadro.com/api/v1 export NEXT_PUBLIC_SITE_URL=https://nomadweb.nomadro.com export CORS_ORIGINS=https://nomadweb.nomadro.com docker compose -f docker-compose.prod.yml up -d --build ``` 或使用 Docker Compose 生产配置: ```bash docker compose -f docker-compose.prod.yml up -d --build cp deploy/caddy/nomadweb.caddy /etc/caddy/sites/nomadweb.caddy systemctl reload caddy ``` ### 本地 Docker Compose ```bash docker compose up -d ``` ### 前端 → Vercel 1. 导入 `frontend/` 目录 2. 环境变量:`NEXT_PUBLIC_API_URL=https://nomadweb.nomadro.com/api/v1` 3. 自动构建部署 ### 后端 → Railway 1. 连接 `backend/` 目录 2. 配置 `POCKETBASE_URL`、`CORS_ORIGINS` 3. 读取 `railway.toml` 自动部署 ## 快捷键 | 按键 | 功能 | |------|------| | `Ctrl+K` | 全局搜索 | | `M` | 智能目的地匹配 | | `?` | 快捷键帮助 | | `Esc` | 关闭弹窗 | ## License MIT