一个简洁美观的笔记应用,支持 H5 和 Web 端,自适应设计,支持明暗主题切换。
- 前端: Svelte + Vite
- 后端: Go + Gin + SQLite
- 特性: 响应式设计、明暗主题、标签系统、用户认证
macOS / Linux:
./start.shWindows:
start.bat脚本会自动:
- ✅ 检查 Go 和 Node.js 环境
- ✅ 安装依赖(Go modules 和 npm packages)
- ✅ 检查并清理端口占用
- ✅ 启动后端服务(:9000)
- ✅ 启动前端应用(:9001)
- ✅ 等待服务就绪后显示访问地址
启动成功后:
- 📝 后端 API: http://localhost:9000
- 🌐 前端应用: http://localhost:9001
你这次要求的「Go 后端托管/内嵌 SvelteKit 静态文件」对应如下脚本:
- 开发模式(热更新):
./dev-kit.sh打开 http://localhost:9001(SvelteKit dev),API 走代理到 http://localhost:9000。
- 生产构建 + 一键启动(Go 直接提供前端静态文件):
./start-prod.sh启动后直接打开 http://localhost:9000。
说明:
- Go 构建时启用了
sqlite_fts5build tag(用于 SQLite FTS5) - SvelteKit 构建产物会同步到
backend/public/,并由 Go 在运行时托管(SPA fallback 到index.html)
目标:别人可以 docker run 或 docker compose up 在 NAS/服务器上自部署,并且数据可持久化。
必填环境变量:
MEMO_JWT_SECRET:JWT 密钥(生产必须设置,建议 32+ 字符)
推荐环境变量:
MEMO_ADMIN_PASSWORD:用于初始化/重置管理员admin的密码(不设置则首次启动会随机生成并打印到容器日志)MEMO_CORS_ORIGINS:允许的前端域名(逗号分隔),例如https://your.domain,https://nas.local
容器数据目录:
/data/notes.db:SQLite 数据库(通过MEMO_DB_PATH指定)/data/storage:附件目录(通过MEMO_STORAGE_DIR指定)
示例:
docker run -d \
--name memo-studio \
-p 9000:9000 \
-v memo_data:/data \
-e MEMO_JWT_SECRET="please-change-me" \
-e MEMO_ADMIN_PASSWORD="your-strong-password" \
-e MEMO_ENV=production \
-e GIN_MODE=release \
memo-studio:local启动后访问:http://localhost:9000
默认管理员用户名:admin
直接使用仓库根目录的 docker-compose.yml:
# 生成强 JWT Secret(必须!)
export MEMO_JWT_SECRET=$(openssl rand -base64 32)
# 启动
docker compose up -d --build或者创建 .env 文件:
# .env 文件
MEMO_JWT_SECRET=your-strong-secret-here
MEMO_ADMIN_PASSWORD=your-admin-password- 生产环境不再固定
admin/admin123 - 若设置了
MEMO_ADMIN_PASSWORD:启动时会确保admin存在并重置密码,同时标记“需要修改密码” - 若没设置且数据库为空:启动会生成随机初始密码,并打印到日志(请登录后立即修改)
PORT:监听端口(默认 9000)MEMO_DB_PATH:SQLite 路径(默认./notes.db;容器建议/data/notes.db)MEMO_STORAGE_DIR:附件目录(默认./storage;容器建议/data/storage)MEMO_CORS_ORIGINS:CORS 白名单(逗号分隔;不填默认放开)MEMO_JWT_SECRET:JWT 密钥(生产必须设置)
配置 OpenAI API Key 启用 AI 功能:
| 环境变量 | 说明 | 默认值 |
|---|---|---|
OPENAI_API_KEY |
OpenAI API Key | 未设置 |
OPENAI_BASE_URL |
API 地址 | https://api.openai.com/v1 |
WHISPER_MODEL |
语音转文本模型 | whisper-1 |
INSIGHT_MODEL |
洞察分析模型 | gpt-4 |
启用后功能:
- 🎤 语音转文本:上传音频自动转文字
- 🧠 AI 洞察:分析笔记关键词、分类、情感
- ✨ AI 总结:自动提取要点、生成任务建议
- 📈 股票分析:实时行情、技术分析、投资建议
建议发布 linux/amd64 与 linux/arm64 两种架构镜像(群晖/威联通/树莓派常用)。
后续可以用 GitHub Actions + buildx 自动构建并推送到 Docker Hub/GHCR。
本仓库已内置 GitHub Actions:推送 tag(如 v0.1.0)会自动构建并推送镜像到 GHCR:
- 镜像地址:
ghcr.io/<你的GitHub用户名>/<仓库名>:latest - 也会推送版本 tag:例如
ghcr.io/<你的GitHub用户名>/<仓库名>:v0.1.0
git tag v0.1.0
git push origin v0.1.0Actions 运行完成后,别人即可部署:
docker run -d \
--name memo-studio \
-p 9000:9000 \
-v memo_data:/data \
-e MEMO_JWT_SECRET="please-change-me" \
-e MEMO_ADMIN_PASSWORD="your-strong-password" \
ghcr.io/<你的GitHub用户名>/<仓库名>:latest很多 NAS 更习惯从 Docker Hub 拉取镜像。本仓库工作流已支持在打 tag 时同步推送 Docker Hub,前提是你配置好 Secrets:
在 GitHub 仓库 Settings → Secrets and variables → Actions 添加:
DOCKERHUB_USERNAME:你的 Docker Hub 用户名DOCKERHUB_TOKEN:Docker Hub Access Token(建议用 token,不要用密码)
发布后 Docker Hub 镜像名规则:
docker.io/<DOCKERHUB_USERNAME>/<仓库名>:latestdocker.io/<DOCKERHUB_USERNAME>/<仓库名>:v0.1.0
别人部署示例:
docker run -d \
--name memo-studio \
-p 9000:9000 \
-v memo_data:/data \
-e MEMO_JWT_SECRET="please-change-me" \
-e MEMO_ADMIN_PASSWORD="your-strong-password" \
docker.io/<你的DockerHub用户名>/<仓库名>:latest本仓库已内置工作流:.github/workflows/ai-pr-review.yml
默认不会对所有 PR 自动评论(避免刷屏/与 Gemini 等机器人冲突)。运行方式如下:
- 特殊规则:Dependabot 提的依赖更新 PR 会自动触发 AI Review(不需要加标签),方便“依赖更新→自动CR→自动合并”全自动闭环
- 方式 A(推荐):给 PR 加上标签
ai-review,工作流就会自动运行并更新同一条评论 - 方式 B:手动触发
AI PR Review工作流,并填写pr_number
工作流会:
- 拉取 PR diff(不 checkout PR 分支代码,避免安全风险)
- 调用你配置的大模型 API
- 在 PR 下发布/更新一条中文 CR 评论
在 GitHub 仓库:Settings → Secrets and variables → Actions → New repository secret 添加:
AI_REVIEW_API_KEY:模型 API Key(必填)AI_REVIEW_MODEL:模型名(必填,例如gpt-4o-mini/gpt-4.1-mini/ 你自建模型名)AI_REVIEW_BASE_URL:可选,OpenAI 兼容接口地址(默认https://api.openai.com/v1)
说明:
- 如果未配置
AI_REVIEW_API_KEY/AI_REVIEW_MODEL,工作流会自动跳过(不报错)
cd backend
go mod download
go run main.go后端服务将在 http://localhost:9000 启动
cd frontend
npm install
npm run dev前端应用将在 http://localhost:9001 启动
- 启动服务后,打开浏览器访问 http://localhost:9001
- 点击"立即注册"创建账号
- 注册成功后自动登录,即可开始使用
memo-studio/
├── backend/ # Go 后端服务
│ ├── main.go # 入口文件
│ ├── database/ # 数据库相关
│ ├── models/ # 数据模型
│ ├── handlers/ # API 处理器
│ ├── middleware/ # 中间件
│ └── utils/ # 工具函数
├── frontend/ # Svelte 前端应用
│ ├── src/
│ │ ├── components/ # 组件
│ │ ├── stores/ # 状态管理
│ │ └── utils/ # 工具函数
│ └── vite.config.js
├── start.sh # 一键启动脚本
└── README.md
- ✅ 用户注册和登录(JWT 认证)
- ✅ 笔记列表展示(瀑布流/时间线模式)
- ✅ 笔记详情查看
- ✅ 新建/编辑笔记
- ✅ 删除笔记(单个/批量)
- ✅ 标签系统(创建、编辑、删除、合并)
- ✅ 高级搜索(关键词、日期、标签筛选)
- ✅ 数据导出(Markdown、JSON、CSV)
- ✅ 明暗主题切换
- ✅ 响应式设计(支持 H5 和 Web)
- ✅ 热力图显示
- ✅ 图片上传与管理(支持粘贴/拖拽)
- ✅ 🎤 语音输入(浏览器语音识别 + 录音)
- ✅ 🧠 AI 洞察分析(关键词、分类、情感)
- ✅ ✨ AI 笔记总结(要点提取、任务建议)
- ✅ 📈 股票分析(实时行情、技术分析)
- ✅ 📍 位置识别(自动检测笔记中的地点)
GET /health- 健康检查端点
POST /api/auth/login- 用户登录- 请求体:
{ "username": "string", "password": "string" } - 返回:
{ "token": "string", "user": {...} }
- 请求体:
POST /api/auth/register- 用户注册- 请求体:
{ "username": "string", "password": "string", "email": "string" } - 返回:
{ "token": "string", "user": {...} }
- 请求体:
GET /api/auth/me- 获取当前用户信息- 需要 Authorization: Bearer
- 返回:
{ "id": number, "username": "string", "email": "string", "created_at": "datetime" }
GET /api/notes- 获取所有笔记- 返回:
[{ "id": number, "title": "string", "content": "string", "tags": [...], "created_at": "datetime", "updated_at": "datetime" }]
- 返回:
GET /api/notes/:id- 获取单个笔记- 返回:
{ "id": number, "title": "string", "content": "string", "tags": [...], "created_at": "datetime", "updated_at": "datetime" }
- 返回:
POST /api/notes- 创建笔记- 请求体:
{ "title": "string", "content": "string", "tags": ["string"] } - 返回: 创建的笔记对象
- 请求体:
PUT /api/notes/:id- 更新笔记- 请求体:
{ "title": "string", "content": "string", "tags": ["string"] } - 返回: 更新后的笔记对象
- 请求体:
DELETE /api/notes/:id- 删除笔记- 返回:
{ "success": true, "message": "笔记已删除" }
- 返回:
DELETE /api/notes/batch- 批量删除笔记- 请求体:
{ "ids": [number] } - 返回:
{ "success": true, "deleted": number, "message": "string" }
- 请求体:
GET /api/tags- 获取所有标签- 返回:
[{ "id": number, "name": "string", "color": "string", "created_at": "datetime" }]
- 返回:
PUT /api/tags/:id- 更新标签- 请求体:
{ "name": "string", "color": "string" } - 返回: 更新后的标签对象
- 请求体:
DELETE /api/tags/:id- 删除标签- 返回:
{ "success": true, "message": "标签已删除" }
- 返回:
POST /api/tags/merge- 合并标签- 请求体:
{ "sourceId": number, "targetId": number } - 返回:
{ "success": true, "message": "标签合并成功" }
- 请求体:
-
POST /api/insights- 获取笔记洞察- 请求体:
{ "notes": ["string"], "time_range": "7d|30d|90d|all" } - 返回:
{ "summary": "string", "keywords": ["string"], "categories": ["string"], "sentiment": "positive|neutral|negative", "trends": ["string"], "tips": ["string"] }
- 请求体:
-
POST /api/summarize- 总结单条笔记- 请求体:
{ "content": "string" } - 返回:
{ "summary": "string", "highlights": ["string"], "action_items": ["string"] }
- 请求体:
-
POST /api/summarize/batch- 批量总结- 请求体:
{ "notes": ["string"], "limit": number } - 返回:
{ "total": number, "limited": number, "results": [...] }
- 请求体:
-
POST /api/speech-to-text- 语音转文本- 请求体: multipart/form-data (file 字段)
- 可选字段:
language,prompt,temperature - 返回:
{ "text": "string", "duration": number, "language": "string", "configured": boolean }
-
POST /api/resources/transcribe- 上传并转录音频- 请求体: multipart/form-data (file 字段)
- 返回:
{ "resource": {...}, "transcribe": { "text": "string", "duration": number, "language": "string" } }
使用 SQLite 数据库,首次运行会自动创建数据库文件 backend/notes.db 和表结构。
数据库表结构:
users- 用户表notes- 笔记表tags- 标签表note_tags- 笔记标签关联表
- Go 1.21+
- Node.js 18+
- npm 或 yarn
前端使用 Vite,默认支持热模块替换(HMR):
- ✅ 修改前端代码后,浏览器会自动刷新
- ✅ 无需手动重启前端服务
- ✅ 修改样式和组件会立即生效
- ✅ 保持应用状态(不会丢失数据)
使用方式:
- 启动服务后,修改
frontend/src/下的任何文件 - 保存文件后,浏览器会自动更新
- 无需任何手动操作
后端 Go 服务默认不支持热重载,有两种方式:
方式一:使用 Air(推荐,自动热重载)
-
安装 Air:
go install github.com/cosmtrek/air@latest
-
在
backend目录运行:cd backend ./start-dev.sh # 或直接运行 air
-
修改 Go 代码后,Air 会自动重新编译和重启服务
方式二:手动重启(简单但需要手动操作)
修改代码后,需要手动停止并重新启动后端服务:
# 停止服务(Ctrl+C)
# 然后重新运行
cd backend
go run main.gobackend.log- 后端服务日志frontend.log- 前端开发服务器日志
macOS / Linux:
在运行 ./start.sh 的终端中按 Ctrl+C 即可停止所有服务。
Windows:
关闭运行 start.bat 的命令窗口即可停止所有服务。
如果 9000 或 9001 端口被占用,启动脚本会自动尝试清理。如果失败,请手动停止占用端口的进程:
# 查看端口占用
lsof -i :9000
lsof -i :9001
# 停止进程(替换 PID)
kill -9 <PID>Go 依赖:
cd backend
go mod download
go mod tidynpm 依赖:
cd frontend
rm -rf node_modules package-lock.json
npm install如果数据库文件损坏,可以删除后重新启动:
cd backend
rm notes.db
# 重新启动服务,数据库会自动创建前端:
- 检查浏览器控制台是否有错误
- 尝试硬刷新(Ctrl+Shift+R 或 Cmd+Shift+R)
- 检查 Vite 开发服务器是否正常运行
后端:
- 确保已安装 Air:
go install github.com/cosmtrek/air@latest - 检查
.air.toml配置文件是否存在 - 查看 Air 的输出日志
MIT License