Checkout new amazing projects also,
OpenReadme is live
© Open Dev Society. This project is licensed under AGPL-3.0; if you modify, redistribute, or deploy it (including as a web service), you must release your source code under the same license and credit the original authors.
# OpenStock
OpenStock 是昂贵市场平台的开源替代方案。它支持追踪实时价格、设置个性化提醒,并探索详细的公司洞察——公开构建,面向所有人,永久免费。
注意:OpenStock 由社区构建,并非券商。市场数据可能会根据提供商的规则和您的配置出现延迟。此处内容均不构成任何财务建议。
## 📋 目录
1. ✨ [简介](#introduction)
2. 🌍 [开放开发者协会宣言](#manifesto)
3. ⚙️ [技术栈](#tech-stack)
4. 🔋 [功能](#features)
5. 🤸 [快速开始](#quick-start)
6. 🐳 [Docker 设置](#docker-setup)
7. 🔐 [环境变量](#environment-variables)
8. 🧱 [项目结构](#project-structure)
9. 📡 [数据与集成](#data--integrations)
10. 🌍 [市场支持](#market-support)
11. 🧪 [脚本与工具](#scripts--tooling)
12. 🤝 [贡献](#contributing)
13. 🛡️ [安全](#security)
14. 📜 [许可证](#license)
15. 🙏 [致谢](#acknowledgements)
## ✨ 简介
OpenStock 是一款现代化的股票市场应用,由 Next.js (App Router)、shadcn/ui 和 Tailwind CSS、用于身份验证的 Better Auth、用于持久化的 MongoDB、用于市场数据的 Finnhub,以及用于图表和市场视图的 TradingView 小部件提供支持。
## 🌍 开放开发者协会宣言
我们生活在一个知识被付费墙隐藏的世界。工具被订阅制牢牢锁定。信息被偏见所扭曲。新人被告知他们“不够好”,不配去创造。
我们相信有更好的方式。
- 我们的信念:技术应属于每一个人。知识应当是开放、免费且触手可及的。社区应当以信任而非设立门槛来欢迎新人。
- 我们的使命:构建产生实际影响的免费、开源项目:
- 专业人士和学生都能无障碍使用的工具。
- 永久免费学习的知识平台。
- 引导而非评判每一位初学者的社区。
- 基于信任而非利润运转的资源。
- 我们的承诺:我们永远不会封闭知识。我们永远不会收取访问费用。我们永远不会以信任换取金钱。我们依靠透明度、捐赠和社区的力量运作。
- 我们的呼吁:如果您曾觉得自己格格不入,曾为寻找免费资源而苦苦挣扎,或者曾想构建有意义的东西——这里就是您的归属。
因为未来属于那些以开放方式创造它的人。
## ⚙️ 技术栈
核心
- Next.js 15 (App Router), React 19
- TypeScript
- Tailwind CSS v4 (通过 @tailwindcss/postcss)
- shadcn/ui + Radix UI 原语
- Lucide 图标
身份验证与数据
- Better Auth(邮箱/密码)搭配 MongoDB adapter
- MongoDB + Mongoose
- Finnhub API(用于股票代码、公司概况和市场新闻)
- TradingView 可嵌入小部件
自动化与通信
- Inngest(事件、cron、通过 Gemini 进行 AI 推理)
- Nodemailer(Gmail 传输)
- next-themes, cmdk(命令面板), react-hook-form
语言构成
- TypeScript (~93.4%), CSS (~6%), JavaScript (~0.6%)
## 🔋 功能
- 身份验证
- 使用 Better Auth + MongoDB adapter 的邮箱/密码验证
- 通过 Next.js middleware 强制实施受保护路由
- 全局搜索和 Command + K 面板
- 由 Finnhub 提供支持的快速股票搜索
- 空闲时显示热门股票;支持防抖查询
- 关注列表
- 存储在 MongoDB 中的按用户区分的关注列表(每位用户的股票代码唯一)
- 股票详情
- TradingView 股票代码信息、蜡烛图/高级图表、基准线、技术指标
- 公司简介和财务小部件
- 针对 Reddit、X.com、新闻和 Polymarket 的可选跨来源情绪洞察
- 市场概览
- 热力图、报价和头条新闻(TradingView 小部件)
- 个性化引导
- 收集国家/地区、投资目标、风险承受能力、偏好行业
- 电子邮件与自动化
- AI 个性化欢迎电子邮件(通过 Inngest 调用 Gemini)
- 每日新闻摘要电子邮件(cron),使用用户关注列表进行个性化
- 精致 UI
- shadcn/ui 组件,Radix 原语,Tailwind v4 设计 token
- 默认采用深色主题
- 键盘快捷键
- Cmd/Ctrl + K 用于快速操作/搜索
## 🤸 快速开始
前置条件
- Node.js 20+ 以及 pnpm 或 npm
- MongoDB 连接字符串(MongoDB Atlas 或通过 Docker Compose 运行的本地实例)
- Finnhub API key(支持免费层级;实时数据可能需要付费版)
- 用于发送电子邮件的 Gmail 账户(或更新 Nodemailer 传输方式)
- 可选:Google Gemini API key(用于 AI 生成的欢迎介绍)
克隆并安装
```
git clone https://github.com/Open-Dev-Society/OpenStock.git
cd OpenStock
# 选择一个:
pnpm install
# 或者
npm install
```
配置环境
- 创建一个 `.env` 文件(见[环境变量](#environment-variables))。
- 验证数据库连通性:
```
pnpm test:db
# 或者
npm run test:db
```
运行开发环境
```
# Next.js dev (Turbopack)
pnpm dev
# 或者
npm run dev
```
在本地运行 Inngest(工作流、cron、AI)
```
npx inngest-cli@latest dev
```
构建并启动(生产环境)
```
pnpm build && pnpm start
# 或者
npm run build && npm start
```
打开 http://localhost:3000 查看应用。
## 🐳 Docker 设置
您可以使用 Docker Compose 轻松运行 OpenStock 和 MongoDB。
1. 确保已安装 Docker 和 Docker Compose。
2. docker-compose.yml 包含两个服务:
- openstock(本应用)
- mongodb(带有持久化卷的 MongoDB 数据库)
3. 创建您的 `.env` 文件(见下方示例)。对于 Docker 设置,请使用如下本地连接字符串:
```
MONGODB_URI=mongodb://root:example@mongodb:27017/openstock?authSource=admin
```
4. 启动技术栈:
```
# 从 repository root
docker compose up -d mongodb && docker compose up -d --build
```
5. 访问应用:
- 应用:http://localhost:3000
- MongoDB 在 Docker 网络内部可通过 host mongodb:27017 访问
注意事项
- app 服务 depends_on mongodb 服务。
- 在 Compose 中为 MongoDB root 用户定义了凭据;root 的连接字符串中必须包含 authSource=admin。
- 数据通过 Docker 卷在重启后依然保留。
可选:本项目使用的 MongoDB 服务定义示例:
```
services:
mongodb:
image: mongo:7
container_name: mongodb
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
volumes:
mongo-data:
```
## 🔐 环境变量
在项目根目录创建 `.env` 文件。选择托管的 MongoDB (Atlas) URI 或本地 Docker URI。
托管型 (MongoDB Atlas):
```
# Core
NODE_ENV=development
# Database (Atlas)
MONGODB_URI=mongodb+srv://
:@/?retryWrites=true&w=majority
# Better Auth
BETTER_AUTH_SECRET=your_better_auth_secret
BETTER_AUTH_URL=http://localhost:3000
# Finnhub
# 注意:Vercel deployment 需要 NEXT_PUBLIC_FINNHUB_API_KEY
NEXT_PUBLIC_FINNHUB_API_KEY=your_finnhub_key
FINNHUB_BASE_URL=https://finnhub.io/api/v1
# Sentiment insights(可选)
ADANOS_API_KEY=your_adanos_api_key
# ADANOS_API_BASE_URL=https://api.adanos.org
# AI Provider(可选,默认:"gemini")
# 支持:"gemini"、"minimax"、"siray"
# AI_PROVIDER=gemini
# Gemini
GEMINI_API_KEY=your_gemini_api_key
# MiniMax(可选,在 AI_PROVIDER=minimax 或作为 fallback 时使用)
# 在 https://platform.minimaxi.com 获取你的 key
# MINIMAX_API_KEY=your_minimax_api_key
# Inngest Signing Key(Vercel deployment 需要)
# 从你的 Inngest dashboard 获取此 Key:https://app.inngest.com/env/settings/keys
INNGEST_SIGNING_KEY=your_inngest_signing_key
# Email(通过 Gmail 的 Nodemailer;如果使用 2FA,请考虑 App Passwords)
NODEMAILER_EMAIL=youraddress@gmail.com
NODEMAILER_PASSWORD=your_gmail_app_password
```
本地 (Docker Compose) MongoDB:
```
# Core
NODE_ENV=development
# Database (Docker)
MONGODB_URI=mongodb://root:example@mongodb:27017/openstock?authSource=admin
# Better Auth
BETTER_AUTH_SECRET=your_better_auth_secret
BETTER_AUTH_URL=http://localhost:3000
# Finnhub
# 注意:Vercel deployment 需要 NEXT_PUBLIC_FINNHUB_API_KEY
NEXT_PUBLIC_FINNHUB_API_KEY=your_finnhub_key
FINNHUB_BASE_URL=https://finnhub.io/api/v1
# Sentiment insights(可选)
ADANOS_API_KEY=your_adanos_api_key
# ADANOS_API_BASE_URL=https://api.adanos.org
# AI Provider(可选,默认:"gemini")
# 支持:"gemini"、"minimax"、"siray"
# AI_PROVIDER=gemini
# Gemini
GEMINI_API_KEY=your_gemini_api_key
# MiniMax(可选,在 AI_PROVIDER=minimax 或作为 fallback 时使用)
# 在 https://platform.minimaxi.com 获取你的 key
# MINIMAX_API_KEY=your_minimax_api_key
# Inngest Signing Key(Vercel deployment 需要)
# 从你的 Inngest dashboard 获取此 Key:https://app.inngest.com/env/settings/keys
INNGEST_SIGNING_KEY=your_inngest_signing_key
# Email(通过 Gmail 的 Nodemailer;如果使用 2FA,请考虑 App Passwords)
NODEMAILER_EMAIL=youraddress@gmail.com
NODEMAILER_PASSWORD=your_gmail_app_password
```
注意事项
- 尽可能将私钥保留在服务端。
- 如果使用 `NEXT_PUBLIC_` 变量,请记住它们会暴露给浏览器。
- 在生产环境中,优先使用专门的 SMTP 提供商,而不是个人 Gmail。
- 不要在 Dockerfile 中硬编码机密;请使用 `.env` 和 Compose。
## 🧱 项目结构
```
app/
(auth)/
layout.tsx
sign-in/page.tsx
sign-up/page.tsx
(root)/
layout.tsx
page.tsx
help/page.tsx
stocks/[symbol]/page.tsx
api/inngest/route.ts
globals.css
layout.tsx
components/
ui/… # shadcn/radix primitives (button, dialog, command, input, etc.)
forms/… # InputField, SelectField, CountrySelectField, FooterLink
Header.tsx, Footer.tsx, SearchCommand.tsx, WatchlistButton.tsx, …
database/
models/watchlist.model.ts
mongoose.ts
lib/
actions/… # server actions (auth, finnhub, user, watchlist)
better-auth/…
inngest/… # client, functions, prompts
nodemailer/… # transporter, email templates
constants.ts, utils.ts
scripts/
test-db.mjs
types/
global.d.ts
next.config.ts # i.ibb.co image domain allowlist
postcss.config.mjs # Tailwind v4 postcss setup
components.json # shadcn config
public/assets/images/ # logos and screenshots
```
## 📡 数据与集成
- Finnhub
- 股票搜索、公司概况和市场新闻。
- 设置 `NEXT_PUBLIC_FINNHUB_API_KEY` 和 `FINNHUB_BASE_URL`(默认:https://finnhub.io/api/v1)。
- 免费层级可能会返回延迟的报价;请遵守速率限制和相关条款。
- Adanos 情绪洞察(可选)
- 跨越 Reddit、X.com、新闻和 Polymarket 的结构化股票情绪快照。
- 设置 `ADANOS_API_KEY`;可选择使用 `ADANOS_API_BASE_URL` 覆盖 API host。
- 仅用于股票详情情绪卡片,不替代 Finnhub 或 TradingView。
- TradingView
- 用于图表、热力图、报价和时间线的可嵌入小部件。
- 来自 `i.ibb.co` 的外部图像已在 `next.config.ts` 中被列入白名单。
- Better Auth + MongoDB
- 搭配 MongoDB adapter 的邮箱/密码验证。
- 通过 middleware 进行 session 验证;大多数路由受保护,公开例外的有 `sign-in`、`sign-up`、静态资源以及 Next 内部组件。
- Inngest
- 工作流:
- `app/user.created` → AI 个性化欢迎电子邮件
- Cron `0 12 * * *` → 针对每位用户的每日新闻摘要
- 本地开发:`npx inngest-cli@latest dev`。
- 电子邮件
- Gmail 传输。更新凭据或切换至您的 SMTP 提供商。
- 用于欢迎和新闻摘要电子邮件的模板。
## 🌍 市场支持
OpenStock 支持 **30 多个国际证券交易所**,包括 NSE、LSE、TSX 等。但是,请注意基于我们的数据提供商存在的一些重要限制。
**简要说明**:
- ✅ Finnhub 支持大多数全球交易所
- ⚠️ TradingView 免费层级对新兴市场(印度 NSE、越南等)有限制
- 📊 免费层级中非美国股票的实时数据会延迟 15 分钟以上
**请参阅 [MARKET_SUPPORT.md](./MARKET_SUPPORT.md) 了解以下内容**:
- 支持交易所的完整列表
- 已知限制与变通方法
- 为什么会出现“This symbol is only available on TradingView”提示
- 如何升级以获得更广泛的市场覆盖
- 计划中的未来改进
有关最新支持的股票代码和交易所,请参阅 [Finnhub 的交易所列表](https://finnhub.io/docs/api/symbol-lookup)。
## 🧪 脚本与工具
包脚本
- `dev`:使用 Turbopack 运行 Next.js 开发服务器
- `build`:生产环境构建(Turbopack)
- `start`:运行生产服务器
- `lint`:ESLint
- `test:db`:验证数据库连通性
开发者体验
- TypeScript 严格模式
- Tailwind CSS v4(无需单独的 tailwind.config)
- 搭配 Radix 原语的 shadcn/ui 组件
- cmdk 命令面板,next-themes,lucide-react 图标
## 🛡️ 安全
如果您发现漏洞:
- 请勿提交公开 issue
- 发送邮件至:opendevsociety@cc.cc
- 我们将协调负责任的披露并迅速进行修补
## 📜 许可证
OpenStock 现在且将永远对所有人免费开放。本项目采用 AGPL-3.0 许可证授权 - 有关详细信息,请参阅 LICENSE 文件。
## 特别感谢
特别感谢 [Adrian Hajdin (JavaScript Mastery)](https://github.com/adrianhajdin) —— 他出色的股票市场应用教程对于在“开放开发者协会”下为开源社区构建 OpenStock 起到了至关重要的作用。
GitHub: [adrianhajdin](https://github.com/adrianhajdin)
YouTube 教程:[股票市场应用教程](https://www.youtube.com/watch?v=gu4pafNCXng)
YouTube 频道:[JavaScript Mastery](https://www.youtube.com/@javascriptmastery)