基于已确认的产品愿景,本文档针对以下决策做出细化方案:种子主题为轴心时代、支持多语言、采用适合开源社区的部署方式,代码 MIT + 内容 CC BY-SA 4.0。
| 层级 | 技术 | 理由 |
|---|---|---|
| 前端框架 | Next.js 15 (App Router) + TypeScript | SSR/SSG 兼顾 SEO 与性能;App Router 支持 RSC 减少客户端 JS |
| 样式 | Tailwind CSS 4 + shadcn/ui | 原子化 CSS、主题切换方便、社区组件丰富 |
| 地图引擎 | MapLibre GL JS (开源) | Mapbox GL JS 的开源分支,无许可费用限制,社区活跃 |
| 时间线 | D3.js 自定义组件 | 灵活度最高,支持从千年到月级缩放 |
| 知识图谱可视化 | Cytoscape.js | 轻量、交互丰富、支持大规模节点 |
| 后端 | Node.js (Next.js API Routes + tRPC) | 前后端类型共享,减少团队技术栈分散 |
| 数据库 (关系) | PostgreSQL + PostGIS | 成熟稳定、GIS 原生支持、开源生态最强 |
| 数据库 (图) | Phase 1 用 PostgreSQL 递归查询;Phase 2 引入 Neo4j | 初期减少运维复杂度,成熟后引入专用图数据库 |
| ORM | Drizzle ORM | TypeScript-first、轻量、支持 PostGIS 扩展 |
| 全文搜索 | Meilisearch | 轻量开源,多语言分词原生支持,部署简单 |
| 内容格式 | MDX (Markdown + JSX 组件) | 写作友好 + 可嵌入交互式地图/时间线组件 |
| i18n | next-intl | Next.js 生态首选,支持服务端/客户端翻译 |
| 认证 | NextAuth.js v5 (Auth.js) | GitHub/Google OAuth + 邮箱/密码 |
| 版本控制引擎 | 自研 (基于 PostgreSQL diff/patch 逻辑) | 针对结构化历史数据的 branch/merge 语义 |
| 对象存储 | S3 兼容 (Cloudflare R2) | 免费出站流量,存储历史图片/地图扫描件 |
| 部署 | Vercel (前端) + Railway/Fly.io (后端/数据库) | 免费额度充足,开源社区常用,全球 CDN |
| CI/CD | GitHub Actions | 与开源社区工作流无缝衔接 |
| Monorepo 管理 | Turborepo | Next.js 团队维护,与生态契合 |
| 被淘汰方案 | 淘汰理由 |
|---|---|
| Vue/Nuxt | React 生态在地图/图谱可视化库方面更丰富 |
| Django/Python 后端 | 增加语言栈分散度,社区贡献者需掌握两种语言 |
| MongoDB | 历史数据关系性强,文档数据库不适合频繁关联查询 |
| Mapbox GL JS | 商业许可有使用量限制,不利于开源社区 |
| Elasticsearch | 过重,Meilisearch 足够且部署更简单 |
| Docker Compose 自托管 | 初期维护成本高,对个人开发者不友好 |
卡尔·雅斯贝尔斯(Karl Jaspers)提出的"轴心时代"(Axial Age,约前 800 - 前 200 年),是人类思想史上最关键的时期之一。在这一时期,中国、印度、波斯、巴勒斯坦和希腊几乎同时独立地产生了深刻的哲学和宗教思想。
这个主题天然适合 TimeMap 的所有维度:
| 维度 | 轴心时代的优势 |
|---|---|
| 🗺️ 地理跨度 | 横跨欧亚五大文明区域,地图视图极其丰富 |
| ⏳ 时间跨度 | ~600 年,可展示思想的并行演进 |
| 🕸️ 关系网络 | 思想家之间的师承、同时代对比、影响链 |
| 📖 叙事深度 | 每个文明区都有独立且丰富的故事线 |
| 🌐 多语言价值 | 天然吸引中/英/希/梵/波 等多语种社区 |
content/axial-age/
├── overview.mdx # 轴心时代总概述
├── civilizations/
│ ├── china/
│ │ ├── overview.mdx # 中国轴心时代概述
│ │ ├── events/
│ │ │ ├── hundred-schools.mdx # 百家争鸣
│ │ │ ├── spring-autumn.mdx # 春秋时期
│ │ │ └── warring-states.mdx # 战国时期
│ │ └── persons/
│ │ ├── confucius.mdx # 孔子
│ │ ├── laozi.mdx # 老子
│ │ ├── mozi.mdx # 墨子
│ │ ├── zhuangzi.mdx # 庄子
│ │ └── sunzi.mdx # 孙子
│ ├── greece/
│ │ ├── overview.mdx # 古希腊概述
│ │ ├── events/
│ │ │ ├── athenian-democracy.mdx # 雅典民主
│ │ │ └── persian-wars.mdx # 波斯战争
│ │ └── persons/
│ │ ├── socrates.mdx # 苏格拉底
│ │ ├── plato.mdx # 柏拉图
│ │ └── aristotle.mdx # 亚里士多德
│ ├── india/
│ │ ├── overview.mdx # 古印度概述
│ │ ├── events/
│ │ │ └── shramana-movement.mdx # 沙门运动
│ │ └── persons/
│ │ ├── buddha.mdx # 释迦牟尼
│ │ └── mahavira.mdx # 大雄 (耆那教)
│ ├── persia/
│ │ ├── overview.mdx # 古波斯概述
│ │ └── persons/
│ │ └── zoroaster.mdx # 琐罗亚斯德
│ └── israel/
│ ├── overview.mdx # 古以色列概述
│ └── persons/
│ ├── isaiah.mdx # 以赛亚
│ └── jeremiah.mdx # 耶利米
├── themes/
│ ├── parallel-thought.mdx # 专题:思想的平行演进
│ ├── trade-routes.mdx # 专题:早期贸易路线与交流
│ └── writing-systems.mdx # 专题:文字系统的演变
└── data/
├── events.json # 事件结构化数据
├── persons.json # 人物结构化数据
├── places.json # 地点 + 坐标数据
├── polities.geojson # 疆域多边形
└── relations.json # 实体关系数据
TimeMap 最独特的展示之一 — 横向对比:
| 时间 | 中国 | 希腊 | 印度 | 波斯 | 以色列 |
|---|---|---|---|---|---|
| ~前 600 | 老子 (道德经) | 泰勒斯 (哲学之父) | 释迦牟尼 (佛教) | 琐罗亚斯德 (拜火教) | 以赛亚 (先知) |
| ~前 500 | 孔子 (儒学) | 赫拉克利特 | 大雄 (耆那教) | 大流士一世 | 以斯拉 |
| ~前 400 | 墨子 (墨学) | 苏格拉底 → 柏拉图 | 波你尼 (语法学) | — | — |
| ~前 300 | 孟子、庄子 | 亚里士多德 | 阿育王 (佛教传播) | 亚历山大征服 | 希腊化影响 |
这张表在 TimeMap 中将以 交互式时间线 + 地图动画 的方式呈现,而非静态表格。
locales/
├── zh/ # 简体中文(首要语言)
│ ├── common.json # UI 通用翻译
│ ├── axial-age.json # 轴心时代内容
│ └── ...
├── en/ # English
├── ja/ # 日本語
├── ko/ # 한국어
├── de/ # Deutsch
├── fr/ # Français
└── es/ # Español
| 层级 | 策略 | 说明 |
|---|---|---|
| UI 界面 | next-intl JSON 文件 |
菜单、按钮等 UI 文本,7 种语言优先 |
| 历史内容 | 每篇 MDX 独立翻译 | 内容翻译由社区贡献者完成,而非机翻 |
| 结构化数据 | 实体名称支持 { zh: "孔子", en: "Confucius" } |
图谱/地图标签自动切换语言 |
| 搜索 | Meilisearch 多语言分词 | 中文 jieba、日文 lindera、西文默认 |
Phase 1:中文 + 英文(双语 MVP) Phase 2:日文、韩文(东亚扩展) Phase 3:德/法/西(全球化)
┌─────────────────────────────────────────────────┐
│ Vercel (前端) │
│ Next.js SSR/SSG + Edge Functions + CDN │
│ ✅ 开源项目免费 Pro 版 │
├─────────────────────────────────────────────────┤
│ Railway (后端 + 数据库) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │PostgreSQL│ │Meilisearch│ │ Redis │ │
│ │+ PostGIS │ │ (搜索) │ │ (缓存) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────┤
│ Cloudflare R2 (对象存储) │
│ 历史图片、地图扫描件、多媒体文件 │
├─────────────────────────────────────────────────┤
│ GitHub (代码 + 内容) │
│ 代码仓库 + 内容版本控制 + GitHub Actions CI/CD │
└─────────────────────────────────────────────────┘
| 优势 | 说明 |
|---|---|
| 低成本 | Vercel 对开源项目免费 Pro;Railway 有免费额度($5/月);R2 免出站 |
| 无需运维 | 托管服务自动伸缩,无需管理服务器 |
| 全球分发 | Vercel CDN 全球 Edge Network |
| 贡献者友好 | git clone → npm install → npm run dev 即可本地开发 |
| Preview 部署 | 每个 PR 自动生成预览 URL,方便内容审核 |
# 一键启动开发环境
git clone https://github.com/yourorg/timemap.git
cd timemap
cp .env.example .env.local
docker compose up -d # 本地 PostgreSQL + Meilisearch
pnpm install
pnpm dev # http://localhost:3000| Git 概念 | TimeMap 概念 | 说明 |
|---|---|---|
| Repository | 历史主题 (Topic) | 如 "轴心时代" |
| Branch | 版本分支 (Branch) | main = 共识版本,个人/学术分支 |
| Commit | 修订 (Revision) | 一次内容修改 |
| Diff | 变更对比 (Change Diff) | 文本 diff + 结构化数据 diff |
| Pull Request | 贡献请求 (Contribution Request, CR) | 提交变更供审核 |
| Merge | 合并 (Merge) | 将 CR 合并到主版本 |
| Fork | 派生 (Fork) | 创建个人独立分支 |
-- 内容版本控制
CREATE TABLE revisions (
id UUID PRIMARY KEY,
topic_id UUID REFERENCES topics(id),
branch_id UUID REFERENCES branches(id),
parent_id UUID REFERENCES revisions(id), -- 前一版本
author_id UUID REFERENCES users(id),
content_hash TEXT NOT NULL, -- 内容哈希
diff_data JSONB, -- 与 parent 的差异
message TEXT, -- 修改说明
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 贡献请求 (CR)
CREATE TABLE contribution_requests (
id UUID PRIMARY KEY,
source_branch UUID REFERENCES branches(id),
target_branch UUID REFERENCES branches(id),
author_id UUID REFERENCES users(id),
title TEXT NOT NULL,
description TEXT,
status TEXT CHECK (status IN ('open','reviewing','approved','merged','rejected')),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- CR 评审
CREATE TABLE cr_reviews (
id UUID PRIMARY KEY,
cr_id UUID REFERENCES contribution_requests(id),
reviewer_id UUID REFERENCES users(id),
decision TEXT CHECK (decision IN ('approve','request_changes','comment')),
comment TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);对于不同类型的内容,采用不同的 diff 策略:
| 内容类型 | Diff 策略 |
|---|---|
| MDX 叙事文本 | 行级文本 diff (类似 git diff) |
| 结构化 JSON (事件/人物) | JSON Patch (RFC 6902) |
| GeoJSON 疆域数据 | 几何差异 + 属性差异 |
| 知识图谱关系 | 三元组增删 (add/remove triples) |
TimeMap/
├── README.md
├── CONTRIBUTING.md
├── LICENSE-CODE (MIT)
├── LICENSE-CONTENT (CC BY-SA 4.0)
├── turbo.json # Turborepo 配置
├── package.json
├── pnpm-workspace.yaml
│
├── apps/
│ └── web/ # Next.js 前端应用
│ ├── app/
│ │ ├── [locale]/ # i18n 路由
│ │ │ ├── page.tsx # 首页
│ │ │ ├── explore/ # 探索 (地图 + 时间线)
│ │ │ ├── topics/ # 历史主题列表
│ │ │ ├── topic/[slug]/ # 主题详情 (阅读视图)
│ │ │ ├── graph/ # 知识图谱视图
│ │ │ ├── contribute/ # 贡献入口
│ │ │ └── community/ # 社区 (讨论/CR)
│ │ └── api/ # API Routes (tRPC)
│ ├── components/
│ │ ├── map/ # 地图组件
│ │ ├── timeline/ # 时间线组件
│ │ ├── graph/ # 图谱组件
│ │ ├── editor/ # MDX 编辑器
│ │ └── ui/ # shadcn/ui 组件
│ ├── lib/
│ │ ├── versioning/ # 版本控制逻辑
│ │ ├── i18n/ # 国际化配置
│ │ └── db/ # 数据库客户端
│ └── messages/ # next-intl 翻译文件
│ ├── zh.json
│ └── en.json
│
├── packages/
│ ├── schema/ # 共享数据模型 (Zod + TypeScript)
│ │ ├── event.ts
│ │ ├── person.ts
│ │ ├── place.ts
│ │ └── relation.ts
│ ├── db/ # Drizzle ORM Schema + 迁移
│ │ ├── schema/
│ │ └── migrations/
│ └── geo/ # GIS 数据处理工具
│ ├── geojson-utils.ts
│ └── coordinate-systems.ts
│
├── content/ # 历史内容 (版本控制在 DB)
│ └── seed/ # 种子数据
│ └── axial-age/ # 轴心时代初始数据
│ ├── events.json
│ ├── persons.json
│ ├── places.json
│ ├── polities.geojson
│ └── articles/
│ ├── zh/ # 中文文章
│ └── en/ # 英文文章
│
├── docker/
│ └── docker-compose.dev.yml # 本地开发用数据库
│
└── docs/
├── architecture.md
├── data-model.md
├── contributing-content.md # 内容贡献指南
└── api-reference.md
目标:一个可运行的"轴心时代"历史知识浏览器,包含阅读 + 地图 + 基础贡献流程
- 初始化 Turborepo + Next.js + Tailwind + shadcn/ui
- 设计并实现 Drizzle ORM 数据库 Schema
- 创建种子数据脚本(10+ 事件、15+ 人物、10+ 地点)
- 设置 GitHub 仓库 + CI/CD + PR 预览
- 首页设计与开发(全球地图 + 轴心时代介绍)
- 条目阅读页面(MDX 渲染 + 侧边栏关联信息)
- 人物/事件/地点列表页 + 搜索
- 中/英双语 UI 框架
- MapLibre GL JS 集成 + 历史底图
- 时间滑块 + 疆域图层动态切换
- D3.js 时间线组件(事件卡片 + 缩放)
- 视图联动(地图 ↔ 时间线 ↔ 阅读页)
- NextAuth.js 集成(GitHub + Google + 邮箱登录)
- Fork → Edit → 提交 CR 基础工作流
- CR 列表页 + 简单评审界面
- 部署到 Vercel + Railway
- 知识图谱可视化(Cytoscape.js 图谱视图)
- CR 完整评审系统(行内评论、变更对比)
- 讨论功能
- 贡献者资料页 + 贡献统计
- Meilisearch 全文搜索集成
- 更多轴心时代内容(社区首批贡献)
- 新主题模板(方便社区开新主题)
- 日/韩/法/德 等语言扩展
- 公开 API (REST + GraphQL)
- 学术引用导出
- 移动端 PWA 适配
- 高级图谱查询(路径搜索、模式匹配)
- 单元测试 (Vitest):数据模型验证、diff 算法、GeoJSON 工具函数
- e2e 测试 (Playwright):阅读页渲染、地图交互、时间线缩放、CR 提交流程
- CI 命令:
pnpm test(单元) +pnpm test:e2e(端到端)
- 多语言切换:切换中/英文后,UI + 内容 + 地图标签全部正确切换
- 地图交互:时间滑块拖到不同时期,疆域图层正确变化
- CR 流程:注册 → Fork → 编辑 → 提交 CR → 另一用户审核 → 合并
- PR 预览:GitHub PR 触发 Vercel Preview 部署,审核者可在预览 URL 查看变更效果
Important
以下几点需要你确认后才能开始开发:
- 项目名称确认:
TimeMap这个名字是否最终确定?需要提前确认以建立 GitHub 仓库和域名 - GitHub 组织:是否创建专门的 GitHub Organization(如
timemap-org),还是先在你的个人账号下? - 是否现在就开始 Phase 1 开发? 如果是,我将从项目脚手架搭建开始
- 种子内容深度:MVP 阶段你希望亲自撰写多少篇文章?建议至少 5 篇核心文章作为样板
- 设计稿:是否需要我先生成首页和核心页面的设计稿供你确认,再进入编码?