diff --git a/VERSION b/VERSION
new file mode 100644
index 00000000..1cf0537c
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.19.0
diff --git a/backend/app/core/config.py b/backend/app/core/config.py
index d7bbb0c2..6d53f83a 100644
--- a/backend/app/core/config.py
+++ b/backend/app/core/config.py
@@ -6,9 +6,16 @@ import os
from pydantic_settings import BaseSettings
+ROOT_DIR = Path(__file__).parent.parent.parent.parent
+VERSION_FILE = ROOT_DIR / "VERSION"
+
+
class Settings(BaseSettings):
PROJECT_NAME: str = "Intelligent Planet Plan"
- VERSION: str = "1.0.0"
+ VERSION: str = (
+ os.getenv("APP_VERSION")
+ or (VERSION_FILE.read_text(encoding="utf-8").strip() if VERSION_FILE.exists() else "0.19.0")
+ )
API_V1_STR: str = "/api/v1"
SECRET_KEY: str = "your-secret-key-change-in-production"
ALGORITHM: str = "HS256"
diff --git a/docs/version-history.md b/docs/version-history.md
new file mode 100644
index 00000000..c2217fe6
--- /dev/null
+++ b/docs/version-history.md
@@ -0,0 +1,76 @@
+# Version History
+
+## Rules
+
+- 初始版本从 `0.0.1-beta` 开始
+- 每次 `bugfix` 递增 `0.0.1`
+- 每次 `feature` 递增 `0.1.0`
+- `refactor / docs / maintenance` 默认不单独 bump 版本
+
+## Assumptions
+
+- 本文基于 `main` 与 `dev` 的非 merge commit 历史整理
+- 对于既包含修复又明显引入新能力的提交,按 `feature` 处理
+- `main` 表示已进入主线,`dev` 表示当前仍在开发分支上的增量
+
+## Current Version
+
+- `main` 当前主线历史推导到:`0.16.5`
+- `dev` 当前开发分支历史推导到:`0.19.0`
+
+## Timeline
+
+| Version | Type | Branch | Commit | Summary |
+| --- | --- | --- | --- | --- |
+| `0.0.1-beta` | bootstrap | `main` | `e7033775` | first commit |
+| `0.1.0` | feature | `main` | `6cb4398f` | Modularize 3D Earth page with ES Modules |
+| `0.2.0` | feature | `main` | `aaae6a53` | Add cable graph service and data collectors |
+| `0.2.1` | bugfix | `main` | `ceb1b728` | highlight all cable segments by cable_id |
+| `0.3.0` | feature | `main` | `14d11cd9` | add ArcGIS landing points and cable-landing relation collectors |
+| `0.4.0` | feature | `main` | `99771a88` | make ArcGIS data source URLs configurable |
+| `0.5.0` | feature | `main` | `de325521` | add data sources config system and Earth API integration |
+| `0.5.1` | bugfix | `main` | `b06cb460` | remove ignored files from tracking |
+| `0.5.2` | bugfix | `main` | `948af2c8` | fix coordinates-display position |
+| `0.6.0` | feature | `main` | `4e487b31` | upload new geo json |
+| `0.6.1` | bugfix | `main` | `02991730` | add cable_id to API response for cable highlighting |
+| `0.6.2` | bugfix | `main` | `c82e1d5a` | 修复 3D 地球坐标映射多个严重 bug |
+| `0.7.0` | feature | `main` | `3b0e9dec` | 统一卫星和线缆锁定逻辑,使用 lockedObject 系统 |
+| `0.7.1` | bugfix | `main` | `11a9dda9` | 修复 resetView 调用并统一启动脚本到 `planet.sh` |
+| `0.7.2` | bugfix | `main` | `e21b783b` | 修复 ArcGIS landing GeoJSON 坐标解析错误 |
+| `0.8.0` | feature | `main` | `f5083071` | 自动旋转按钮改为播放/暂停图标状态 |
+| `0.8.1` | bugfix | `main` | `777891f8` | 修复 resetView 视角和离开地球隐藏 tooltip |
+| `0.9.0` | feature | `main` | `1189fec0` | init view to China coordinates |
+| `0.10.0` | feature | `main` | `6fabbcfe` | request geolocation on resetView, fallback to China |
+| `0.11.0` | feature | `main` | `0ecc1bc5` | cable state management, hover/lock visual separation |
+| `0.12.0` | feature | `main` | `bb6b18fe` | satellite dot rendering with hover/lock rings |
+| `0.13.0` | feature | `main` | `3fcbae55` | add cable-landing point relation via `city_id` |
+| `0.14.0` | feature | `main` | `96222b9e` | toolbar layout and cable breathing effect improvements |
+| `0.15.0` | feature | `main` | `49a9c338` | toolbar and zoom improvements |
+| `0.16.0` | feature | `main` | `78bb639a` | toolbar zoom improvements and toggle-cables |
+| `0.16.1` | bugfix | `main` | `d9a64f77` | fix iframe scrollbar issue |
+| `0.16.2` | bugfix | `main` | `af29e90c` | prevent cable hover/click when cables are hidden |
+| `0.16.3` | bugfix | `main` | `eabdbdc8` | clear lock state when hiding satellites or cables |
+| `0.16.4` | bugfix | `main` | `0c950262` | fix satellite trail origin line and sync button state |
+| `0.16.5` | bugfix | `main` | `9d135bf2` | revert unstable toolbar change |
+| `0.16.6` | bugfix | `dev` | `465129ee` | use timestamp-based trail filtering to prevent flash |
+| `0.17.0` | feature | `dev` | `1784c057` | add predicted orbit display for locked satellites |
+| `0.17.1` | bugfix | `dev` | `543fe35f` | fix ring size attenuation and breathing animation |
+| `0.17.2` | bugfix | `dev` | `b9fbacad` | prevent selecting satellites on far side of earth |
+| `0.17.3` | bugfix | `dev` | `b57d69c9` | remove debug console.log for ring create/update |
+| `0.17.4` | bugfix | `dev` | `81a0ca5e` | fix back-facing detection with proper coordinate transform |
+| `0.18.0` | feature | `dev` | `ef0fefdf` | persist system settings and refine admin layouts |
+| `0.18.1` | bugfix | `dev` | `cc5f16f8` | fix settings layout and frontend startup checks |
+| `0.19.0` | feature | `dev` | `020c1d50` | refine data management and collection workflows |
+
+## Maintenance Commits Not Counted as Version Bumps
+
+这些提交被视为维护性工作,因此未单独递增版本号:
+
+- `3145ff08` Add `.gitignore` and clean
+- `4ada75ca` new branch
+- `c2eba54d` 整理资源文件,添加 legacy 路由
+- `82f7aa29` 提取地球坐标常量到 `EARTH_CONFIG`
+- `d18e400f` remove dead code
+- `869d661a` abstract cable highlight logic
+- `4f922f13` extract satellite config to `SATELLITE_CONFIG`
+- `3e3090d7` docs: add architecture refactor and webgl instancing plans
diff --git a/frontend/package.json b/frontend/package.json
index 53c725ab..4e2d4472 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "planet-frontend",
- "version": "1.0.0",
+ "version": "0.19.0",
"private": true,
"dependencies": {
"@ant-design/icons": "^5.2.6",
diff --git a/frontend/src/components/AppLayout/AppLayout.tsx b/frontend/src/components/AppLayout/AppLayout.tsx
index 74167315..e5ca1b44 100644
--- a/frontend/src/components/AppLayout/AppLayout.tsx
+++ b/frontend/src/components/AppLayout/AppLayout.tsx
@@ -11,6 +11,7 @@ import {
} from '@ant-design/icons'
import { Link, useLocation } from 'react-router-dom'
import { useAuthStore } from '../../stores/auth'
+import packageJson from '../../../package.json'
const { Sider, Content } = Layout
const { Text } = Typography
@@ -24,6 +25,7 @@ function AppLayout({ children }: AppLayoutProps) {
const { user, logout } = useAuthStore()
const [collapsed, setCollapsed] = useState(false)
const showBanner = true
+ const appVersion = `v${packageJson.version}`
const menuItems = [
{ key: '/', icon: