#18
AstronomyNASA APODDeep SpaceAstrophysics

AstroDaily — Daily Astronomy & Deep Sky Explorer

Immersive daily astronomy application powered by NASA APOD and edge computing, delivering high-resolution cosmic imagery accompanied by bilingual astrophysical explanations.

Application & Engineering Screenshots

1 views
AstroDaily Observation View
AstroDaily Observation View

Technical Specifications & Architecture

AstroDaily-cn 🌌 | 每日星图

AstroDaily-cn Banner

基于 NASA APOD、AI 多语言翻译与阿里云边缘计算的现代沉浸式天文观测应用

React 19 Vite 6 Tailwind CSS 4 TypeScript Aliyun AI Models License


📖 项目简介

AstroDaily-cn(每日星图) 是一个设计精致、性能优异的深空天文观测 Web 应用。每天自动抓取 NASA APOD(Astronomy Picture of the Day,每日天文一图),利用前沿大语言模型(Groq / Gemini / 混元)自动生成 8 种语言的通俗天文科普解析,并通过阿里云边缘安全加速(ESA Pages + Edge Routine + 边缘 KV)与 OSS 对象存储实现低延迟、高可靠的全球快速分发。

无论是作为日常天文爱好者探索宇宙的窗口,还是作为个人桌面/手机壁纸来源,每日星图都能带来极致的沉浸体验。


✨ 核心功能

🌌 观测与探索

  • 🖼️ NASA 天文图片与高清画质:每日自动同步 APOD 原版数据,提供标清缩略展示与高清原图预览/下载。
  • 🎥 动态视频媒体支持:无缝支持 NASA 发布的科普视频(YouTube 嵌入播放、MP4 边缘代理与原生下载)。
  • 🎲 随机漫游 (Cosmic Odyssey):一键跨越时空,随机跃迁至历史上的某一个星空奇迹。
  • 📅 天文日历导航:按日期自由穿梭,具备可用日期高亮指示与一键直达“今日最新”功能。
  • ⏱️ 智能时区校准:自动计算 NASA 美东发布时间与用户本地时区的时差转换,确保日期显示精准无误。

🎨 沉浸与交互

  • 🎬 全屏幻灯片 (Slideshow):支持沉浸式自动放映模式,可调节播放方向、暂停/播放与播放间隔。
  • 📱 壁纸设备实时模拟:提供 Desktop 桌面、Tablet 平板、Mobile 手机三种视口的实时壁纸适配效果预览。
  • 💌 星空分享卡片生成:内置 Canvas 引擎,动态渲染排版典雅的高清分享图,支持一键复制到剪贴板或下载 PNG。
  • ❤️ 航行日志与本地收藏:本地持久化保存喜爱的观测记录,支持 JSON 格式日志导出备份与随时导入恢复。
  • 🌓 明暗双主题:深度调校的深空深色模式与典雅浅色模式,一键无缝切换。
  • ⌨️ 快捷键支持:
    • ← / →:切换前一日 / 后一日观测
    • 空格键:开启 / 暂停全屏幻灯片放映
    • Esc:退出全屏沉浸模式与弹窗

🛡️ 可用性与边缘容灾

  • ⚡ 全球边缘极速访问:通过阿里云 ESA 边缘计算,元数据由最近的边缘节点读取,静态资源毫秒级响应。
  • 🛡️ 双层降级容灾自愈:请求日期未缓存时自动回退就近可用历史记录;完全冷启动或网络故障时呈现交互式太空引导页,绝不白屏。
  • 🌐 无感跨域代理:边缘函数拦截 OSS 默认下载头,强制转换为 inline 内联展示,解决国内直接访问 OSS 的排版与防盗链难题。

🏗️ 系统架构

本项目采用存算分离与边缘加速的现代 Serverless 架构设计:

┌────────────────────────────────────────────────────────────────────────┐
│                               用户浏览器                                │
│        React 19 SPA (Vite + Tailwind CSS 4 + Lucide Icons + Motion)    │
│                     ↓ 请求 /api/apod/metadata, /api/image-proxy         │
├────────────────────────────────────────────────────────────────────────┤
│                       阿里云 ESA (边缘安全加速)                          │
│   ┌────────────────────────────────────────────────────────────────┐   │
│   │ ESA Pages (静态资源托管) + Edge Routine 边缘函数 (src/entry.js) │   │
│   │  ├─ /api/apod/metadata   → 读取 ESA KV 边缘键值缓存             │   │
│   │  ├─ /api/image-proxy     → 代理/重定向至 OSS,覆写 Content-Disp │   │
│   │  └─ /api/video-proxy     → 代理视频流与附件下载                 │   │
│   └───────────────┬───────────────────────────────┬────────────────┘   │
│                   │                               │                    │
│             ┌─────▼─────┐                   ┌─────▼─────┐              │
│             │  ESA KV   │                   │  阿里云   │              │
│             │ 元数据存储 │                   │ OSS 存储桶 │              │
│             │(180天 TTL)│                   │(180天生命) │              │
│             └───────────┘                   └───────────┘              │
├────────────────────────────────────────────────────────────────────────┤
│                      阿里云 ECS 虚拟主机 (Crontab)                       │
│   Python 同步流水线 (sync_nasa_to_aliyun.py)                            │
│   1. 定时拉取 NASA APOD API 原始数据                                    │
│   2. 调用 Groq AI (llama-3.3-70b) 高速并发翻译 7 国语言                │
│   3. 下载图片/视频并直传阿里云 OSS                                      │
│   4. 组装元数据与 OSS URL 写入 ESA KV,自动剪裁保持 180 天目录索引     │
└────────────────────────────────────────────────────────────────────────┘

技术栈一览

模块 技术选型 说明
前端视图 React 19 + TypeScript + Motion 现代响应式 UI 与优雅微交互动效
前端样式 Tailwind CSS 4 + Lucide React 极简、现代的深空美学与丰富图标集
构建体系 Vite 6 + esbuild 极速冷启动与热重载,生产代码极度精简
边缘计算 阿里云 DCDN ESA Edge Routine ES 模块标准边缘函数,负责 API 路由与 OSS 代理
元数据存储 阿里云 ESA KV 全球分布式边缘键值,单键 ~11KB,配置 180 天相对 TTL
媒体存储 阿里云 OSS (对象存储) 公共读 Bucket,承载高清大图与视频,配置 180 天生命周期规则
AI 翻译引擎 Groq (llama-3.3-70b-versatile) 极速推理,平均 1~2 秒完成全语言高质量专业天文学翻译
备选 AI 腾讯混元 (hy-mt2-pro) / Gemini 2.0 提供混元脚本变体与本地开发 Gemini 支持
本地服务 Node.js + Express + tsx 本地开发集成环境,内置 NASA API 直接调用与文件缓存

📂 项目结构说明

AstroDaily-cn/
├── src/                          # 前端源码
│   ├── App.tsx                   # 应用核心逻辑(状态管理、媒体渲染、幻灯片、快捷键等)
│   ├── main.tsx                  # React DOM 挂载入口
│   ├── types.ts                  # TypeScript 类型定义与多语言 UI 静态词典
│   ├── index.css                 # 全局样式与 Tailwind 指令
│   ├── entry.js                  # 阿里云 ESA Edge Routine 边缘 API 入口
│   └── components/               # 核心功能组件
│       ├── Header.tsx            # 顶部操作栏(多语言切换、深浅主题、收藏夹入口、免责声明)
│       ├── CalendarPopover.tsx   # 交互式日历弹窗(支持可用日期高亮与快速年月翻转)
│       ├── StarfieldLoader.tsx   # 优雅的星空十字准星加载动效与进度条
│       ├── WallpaperPreview.tsx  # 多端设备壁纸模拟预览(桌面/平板/手机)
│       ├── ShareCardModal.tsx    # Canvas 动态生成与导出高清星空分享卡片
│       ├── FavoritesManager.tsx  # 本地收藏夹管理器(支持 JSON 导出/导入)
│       └── DisclaimerModal.tsx   # 多语言免责声明与 NASA 版权说明对话框
│
├── api/
│   └── index.ts                  # 本地开发与备选 Node.js Express 后端路由
│
├── server.ts                     # 本地集成开发服务器(Vite HMR 中间件 + Express)
│
├── sync_nasa_to_aliyun.py        # 【核心】阿里云云端定时同步脚本(NASA → Groq → OSS + ESA KV)
├── sync_nasa_to_aliyun_hy-mt2-pro.py  # 阿里云同步脚本变体(采用腾讯混元模型)
├── fetch_nasa_apod_groq.py       # 本地离线抓取工具(仅拉取并使用 Groq 翻译到本地 nasa_data)
├── fetch_nasa_apod_hy-mt2-pro.py # 本地离线抓取工具(腾讯混元变体)
├── upload_to_aliyun.py           # 本地数据补录工具(将本地 nasa_data 目录批量推送到 OSS/KV)
├── upload_to_kv_patched.py       # 历史补丁工具(Cloudflare 迁移遗留参考)
│
├── nasa_data/                    # 本地抓取/缓存的 APOD 数据集(按 YYYY-MM-DD 归档)
├── assets/                       # 静态资源与媒体
│
├── Aliyun_Deployment_Guide.md    # 阿里云保姆级部署指南(OSS/KV/RAM/ECS 全流程)
├── DEVNOTES.md                   # 开发与架构踩坑笔记(SPA 回退/OSS 代理/CORS)
├── esa.jsonc                     # 阿里云 ESA Pages 部署配置文件
├── vercel.json                   # Vercel 备选部署配置文件
├── vite.config.ts                # Vite 6 构建配置
├── tsconfig.json                 # TypeScript 编译配置
├── package.json                  # NPM 项目依赖与构建指令
└── .env.example                  # 环境变量配置模板

🚀 快速开始

1. 环境准备

  • Node.js:18.0.0 或更高版本
  • npm:9.0.0 或更高版本
  • Python(可选,仅运行同步脚本需要):3.8+ 及对应依赖

2. 安装项目依赖

# 克隆仓库
git clone https://github.com/misterye/AstroDaily-cn.git
cd AstroDaily-cn

# 安装前端依赖
npm install

3. 配置本地环境变量

复制模板并按需填写:

cp .env.example .env

.env 配置文件说明:

# NASA API 密钥(可选,不填默认使用官方 DEMO_KEY,限额 30~50次/小时)
NASA_API_KEY="YOUR_NASA_API_KEY"

# Google Gemini API 密钥(本地开发模式下若需要实时 AI 翻译则配置)
GEMINI_API_KEY="YOUR_GEMINI_API_KEY"

💡 提示:即使不配置任何 API Key,本地开发服务器依然能够启动并正常工作(系统会自动启用容灾演示数据集与 DEMO_KEY)。

4. 启动本地开发服务

npm run dev

启动后在浏览器打开 http://localhost:3000 即可开始体验!


🛠️ NPM 指令一览

指令 说明 适用场景
npm run dev 启动开发服务器(Vite 实时热重载 + 本地 Express 代理) 本地功能开发与调试
npm run build 完整构建前端(dist/)和后端服务端(dist/server.cjs) 生产全栈部署 / Docker
npm run build:pages 仅构建前端静态资源至 dist/ 目录 阿里云 ESA Pages 部署(推荐)
npm run start 运行生产编译后的 Node.js 服务 本地测试生产包
npm run clean 清除 dist 构建产物和临时生成物 构建缓存清理
npm run lint 执行 TypeScript 静态类型检查(tsc --noEmit) CI/CD 与提交前检查

🌐 部署指南

方案 A:阿里云 ESA Pages + OSS(推荐生产环境 ⭐)

本项目生产环境完全运行在阿里云基础设施上,具有国内访问延迟低、全球多节点 CDN 加速和免运维等优势。

  • 前端与 API:通过 ESA Pages 部署前端静态包,API 请求交由 src/entry.js 边缘函数处理。
  • 存储:ESA KV 承载元数据(180 天 TTL),OSS 承载大图与视频(配置 180 天生命周期)。
  • 同步:ECS 定时任务执行 Python 脚本拉取并同步。

👉 点击查阅:阿里云保姆级部署指南 (Aliyun_Deployment_Guide.md)(包含创建 Bucket、跨域 CORS 配置、RAM 授权、ESA KV 创建、Crontab 配置的详尽步骤)。

esa.jsonc 配置文件:

{
  "name": "astrodaily-cn",
  "entry": "./src/entry.js",          // 边缘函数入口
  "buildCommand": "npm run build:pages", // 静态构建指令
  "assets": {
    "directory": "./dist",
    "notFoundStrategy": "singlePageApplication" // SPA 路由回退
  }
}

方案 B:Vercel(备用方案)

项目包含 vercel.json,可一键部署至 Vercel:

npm i -g vercel
vercel

在 Vercel 仪表盘中配置环境变量:

  • NASA_API_KEY
  • GEMINI_API_KEY

方案 C:Docker 容器化部署

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
ENV NODE_ENV=production
EXPOSE 3000
CMD ["npm", "start"]
docker build -t astrodaily-cn .
docker run -d -p 3000:3000 \
  -e NASA_API_KEY="your_key" \
  -e GEMINI_API_KEY="your_key" \
  --name astrodaily astrodaily-cn

🔌 API 接口规范

前端与边缘函数(src/entry.js)及本地后端(api/index.ts)完全解耦,支持以下标准化 RESTful 端点:

1. 获取 APOD 元数据

GET /api/apod/metadata(或重定向入口 GET /api/apod)

  • 请求参数:

    • date(string,可选):目标日期,格式 YYYY-MM-DD。缺省时自动返回最新已发布的记录。
  • 成功响应示例 (200 OK):

    {
      "date": "2026-07-05",
      "title": "M27: The Dumbbell Nebula",
      "explanation": "The first hint of what will become of our Sun was discovered...",
      "url": "https://astrodaily-assets.oss-cn-shanghai.aliyuncs.com/media/2026-07-05/image_standard.jpg",
      "hdurl": "https://astrodaily-assets.oss-cn-shanghai.aliyuncs.com/media/2026-07-05/image_hd.jpg",
      "media_type": "image",
      "copyright": "Francesco Antonucci",
      "translations": {
        "zh-CN": { "title": "M27:哑铃星云", "explanation": "..." },
        "zh-TW": { "title": "M27:啞鈴星雲", "explanation": "..." },
        "ja": { "title": "M27:亜鈴状星雲", "explanation": "..." },
        "ko": { "title": "...", "explanation": "..." },
        "de": { "title": "...", "explanation": "..." },
        "fr": { "title": "...", "explanation": "..." },
        "es": { "title": "...", "explanation": "..." },
        "en": { "title": "M27: The Dumbbell Nebula", "explanation": "..." }
      },
      "from_cache": true,
      "available_dates": ["2026-07-05", "2026-07-04", "..."]
    }
    

2. 边缘图片代理与下载

GET /api/image-proxy

  • 功能:由边缘函数反向代理阿里云 OSS 图片。解决直接请求 OSS 默认域名时强制下载的问题,并处理前端 Canvas 跨域绘制。
  • 请求参数:
    • date(string,必须):YYYY-MM-DD
    • type(string,必须):standard(标清)或 hd(高清原图)
    • download(boolean,可选):为 true 时响应头附加 Content-Disposition: attachment; filename="NASA-APOD-...",触发浏览器原生另存为。

3. 视频代理与下载

GET /api/video-proxy

  • 功能:针对 media_type === "video" 的 APOD 内容,提供 MP4 视频媒体流代理或重定向至原始视频载荷。
  • 请求参数:
    • date(string,必须):YYYY-MM-DD
    • type(string,可选):standard 或 hd,默认 standard
    • download(boolean,可选):为 true 时强制附带视频文件下载响应头。

4. 边缘图片预热(Prewarm)

GET /api/apod/prepare-image

  • 功能:用于前端客户端提前向边缘节点发起预加载与缓存命中探测。

🔄 数据同步流水线 (Python)

数据同步通过运行在阿里云 ECS 上的 Python 脚本全自动执行。

1. Python 环境与依赖

pip install requests yt-dlp oss2 alibabacloud_esa20240910 alibabacloud_tea_openapi

⚠️ 注意:yt-dlp 是解析与下载 NASA 官方每日视频必须的依赖组件;oss2 与 alibabacloud_esa20240910 为阿里云官方 SDK。

2. 同步脚本命令与参数

主线脚本为 sync_nasa_to_aliyun.py:

# 1. 抓取并同步今天的数据(美东时间当前自然日)
python sync_nasa_to_aliyun.py

# 2. 同步指定历史日期的天文数据
python sync_nasa_to_aliyun.py --date 2026-07-05

# 3. 批量同步最近 N 天的数据(回溯近半个月)
python sync_nasa_to_aliyun.py --days 15

# 4. 强制覆盖已同步记录(忽略 aliyun_synced 标记重新拉取并更新)
python sync_nasa_to_aliyun.py --date 2026-07-05 --force

3. 配置 Crontab 定时自动运行

NASA 通常在美东时间午夜 00:00~01:00(即北京时间当天 13:00~14:00)更新当日天文一图。建议在 ECS 上设置每日 14:00 自动拉取最近 3 天数据:

crontab -e

添加以下定时任务:

# 每日北京时间 14:00 自动执行同步,输出追加记录至日志
0 14 * * * cd /data/AstroDaily-cn && /usr/bin/python3 sync_nasa_to_aliyun.py --days 3 >> /data/AstroDaily-cn/apod_data_handle_log.txt 2>&1

4. 辅助维护脚本说明

  • upload_to_aliyun.py:如果本地磁盘的 nasa_data/ 目录已有此前抓取好的历史数据,可运行该脚本一次性全部批量推送到 OSS 和 ESA KV。
  • fetch_nasa_apod_groq.py:仅在本地抓取 APOD 数据并通过 Groq 翻译保存到本地,适合单机测试或完全离线使用场景。
  • sync_nasa_to_aliyun_hy-mt2-pro.py:采用腾讯混元 AI 大模型作为翻译引擎的变体脚本。

🌍 多语言支持矩阵

每日星图从 UI 界面交互到每日科普内容,全面适配以下 8 种语言:

语言代码 语言名称 地区 翻译模型 时区对应
zh-CN 简体中文 中国大陆 Groq / 混元 Asia/Shanghai
zh-TW 繁體中文 港澳台地区 Groq / 混元 Asia/Taipei
en English 美国/全球 原始 NASA 文案 America/New_York
ja 日本語 日本 Groq / 混元 Asia/Tokyo
ko 한국어 韩国 Groq / 混元 Asia/Seoul
de Deutsch 德国/欧洲 Groq / 混元 Europe/Berlin
fr Français 法国/欧洲 Groq / 混元 Europe/Paris
es Español 西班牙/拉美 Groq / 混元 Europe/Madrid

🔧 常见故障排查 (Troubleshooting)

1. 点击下载按钮时,下载的是一个几百字节的 HTML 文件?

  • 根因:使用了 <a download> 标签触发下载。在静态单页应用(SPA)托管环境下,浏览器发出的属于导航请求(Navigation Request),被 ESA Pages 的 notFoundStrategy: "singlePageApplication" 策略拦截并重定向返回了 index.html。
  • 解决方式:项目中已全面改造为 fetch() 请求子资源 + URL.createObjectURL(blob) 方案触发原生下载。详见 开发踩坑笔记 (DEVNOTES.md)。

2. 在前端使用 Canvas 生成分享图时提示跨域错误(Tainted Canvas)?

  • 根因:OSS Bucket 未开放跨域访问,或跨域规则未暴露 Content-Length、ETag 等头。
  • 解决方式:登录阿里云 OSS 控制台 -> 数据安全 -> 跨域设置 (CORS),允许 * 或前端域名,并确保 Method 勾选了 GET 和 OPTIONS。

3. 直接通过 OSS 链接打开图片却自动弹出了浏览器下载窗口?

  • 根因:阿里云 OSS 默认域名强制绑定了 Content-Disposition: attachment。
  • 解决方式:前端所有媒体渲染均通过 ESA Edge Routine 边缘路由 /api/image-proxy,边缘函数已将响应头覆写为 Content-Disposition: inline。

4. AI 翻译失败或超时?

  • 翻译流程具备完全的非阻塞与容错机制。若 Groq/Gemini 接口限流或超时,系统将自动回退展示 NASA 英文原文,不影响元数据与媒体资产的正常入库。

📄 软件协议

本项目基于 MIT License 开源发布。


🙏 致谢与灵感


探索浩瀚星空,记录宇宙心跳 · Made with ❤️ for Stargazers Everywhere