折腾笔记

折腾笔记

NetNav|把整个局域网装进一个浏览器标签页

2026-09-09

为什么要做这个

家里跑着一台常年不关机的小主机,上面挂着 NAS、几台虚拟机、路由器后台,还有一堆自己搭的服务。用久了,有几个点越来越别扭:

  • 内网服务越来越多,IP 和端口全靠脑子记,过两周就忘,每次都得翻备忘录或者重新扫一遍端口;
  • 现成的导航页(Homepage、Dashy、Heimdall 这些)都很漂亮,但它们只解决「书签」这一件事——天气、备忘、API 余额这种高频信息,还是没地方放;
  • 想看一眼某台虚拟机是不是还开着,得专门打开虚拟化平台的管理后台,登录、等待、再点进去,就为了看一个状态灯;
  • 书签、密钥、内网拓扑这些东西,放在别人家的服务器上总觉得不踏实,数据我想 100% 留在本地。

现成的都不满足,那就自己写一个。目标很明确:一个跑在局域网里、用浏览器打开就能用的导航首页,它不只是书签墙,而是整个内网的控制面板。

于是有了 NetNav:前端 React + Vite,后端一个 Express 单文件服务,数据全部落在本地 JSON 里,部署在任何一台常开的小主机上,全家设备打开浏览器就能用。

长什么样

整体走毛玻璃(glassmorphism)路线:半透明面板 + 背景模糊 + 细腻的动态渐变背景,深浅两套主题 1 秒内热切换。主题切换时背景渐变会跟着明暗自动配对,不会出现在暗色模式下还留着一套刺眼亮背景的情况。

首页亮色总览

主区域是书签卡片网格,每张卡片会尝试自动抓取站点图标;右上角那条「顶栏」,把所有小组件收在一起,不占正文空间。下面是同一套界面的暗色形态:

暗色主题总览

功能

顶栏:可拖拽排序的功能区

顶栏是整套系统最灵活的部分。每个模块都是一个独立小组件,可以在设置里勾选显示、拖拽调顺序,顺序存在浏览器本地,换设备不会互相打架。

默认模块依次是:时钟、API 余额、天气、备忘录、文件、压缩、虚拟机监控、提醒事项、设置。

顶栏功能区

天气

城市可以手动配置,面板展示实时温度、体感温度、湿度、风速和天气描述,未来几天的天气也在同一屏里列出来。数据由服务端拉取并缓存,避免每次开页面都去打一次外部接口。

天气面板

备忘录

不需要笔记软件那套重型同步体系,这里只解决两件事:记下来 和 看得见。支持多条目、时间戳、完成划线,内容以纯文本存在本地 JSON 里;因为全家访问的是同一个内网地址,天然就是「跨设备同步」。

备忘录面板

API 余额

接入大模型 API 之后,最大的焦虑是「这个月额度还剩多少」。这个面板直接查余额,把总余额、已用、剩余额度摊开显示,并附一条按每日消耗推算的本地费用估算——跑长任务之前瞄一眼,心里踏实。密钥只写在服务端配置,前端拿不到。

余额面板

文件与压缩

临时传个文件到内网、或者把几张图打个包,不用再开 FTP 客户端。文件上传后走 /api/files 管理,支持下载和删除;压缩模块直接在页面上把选中的文件打包,少了一次「下下来再传上去」的往返。

提醒事项

到期提醒,和备忘录分开——备忘是「记下来」,提醒是「到时候叫我一声」。

虚拟化平台监控

内网跑着一套虚拟化平台,里面有几台开发测试用的虚拟机。这个面板通过平台 API 读取每台 VM 的状态,在线的带绿色状态点,点击可以直接开机、关机、重启。自打有了它,半夜想重启个服务再也不用爬起来开电脑——手机浏览器打开导航页就能操作。

连接信息(地址、账号、密码)只写在服务端配置里,前端只能拿到状态和发起操作。

PVE 虚拟机面板

设置

设置面板主要承担三件事:顶栏模块的显示与排序、主题切换(亮 / 暗 / 跟随背景)、以及数据的一键导出与导入(整份书签和配置导出成一个 JSON)。加上右键快捷操作和背景图自定义这些小功能,日常使用基本不用再碰配置文件。

设置面板

移动端

整套布局是响应式的,手机上同样能用。把导航页设成浏览器主页之后,手机解锁 → 打开浏览器 → 所有内网服务都在手边,当遥控器用。

移动端视图

怎么搭的

技术栈很常规,没有花活:

层 选型
前端 React 18 + Vite
状态 Zustand(带持久化)
后端 Node.js + Express(单文件)
数据 JSON 文件直读直写
样式 手写 CSS + 毛玻璃动效

架构上只有一个原则:一个端口搞定所有事。前端构建产物 dist/ 和 /api 接口由同一个 Express 服务托管,部署时直接 node server/index.js,不需要配反向代理,也不需要管跨域。

每个监控类模块都套用同一种结构:后端一个 /status 接口去轮询目标服务,一个 /config 接口保存连接信息(密码只存后端、不回传前端),前端小组件定时拉取刷新。所以后来加虚拟机监控的时候,几乎是照着模板抄一遍就长出来了。

踩坑记录

挑几个印象最深的记录一下:

1. Node 没有热重载

后端是单文件 Express,改完 server/index.js 必须手动重启才生效。更烦的是端口释放后有 TIME_WAIT,立刻重启会报 EADDRINUSE,得等一会儿才能重新绑定。后来固定成「改完必重启、重启前先确认端口放掉」的习惯,才算不踩。

2. 内网自签证书

虚拟化平台的 API 走 HTTPS,但证书是自签的、CN 还对不上内网 IP。Node 侧直接请求会校验失败,而且是静默失败——没有任何报错,只是数据一直拿不到。最后在服务端显式关掉证书校验(局域网内自用的妥协)。放到公网的话,请务必换成正规证书。

3. 密钥不能回传前端

最初图省事,把配置的账号密码一起返给前端表单回填,后来意识到只要开个开发者工具就全看见了。改成 /config 只写不读:密码能从前端存进去,但永远读不出来,前端只拿「是否已配置」这个状态。

4. 截图要脱敏

这篇文章的配图是真实界面,但里面的书签、密钥、内网地址不能露。做法是把 data.json 临时换成一份脱敏样例数据、截完图再还原,还原后还做了字节级比对确认一致。中间 notes.json 被脱敏残留污染过一次,从备份恢复才干净——备份这一步不能省。

5. 文章目录(TOC)一直不生成

主题用 tocbot 在前端生成目录,它要求标题必须带 id 锚点。而 Halo 渲染 markdown 产出的 <h2> 默认是没有 id 的,所以目录容器永远是空的。解法是在 markdown 里直接写带 id 的 HTML 标题,例如 <h2 id="sec-2">长什么样</h2>——Halo 会原样保留这些 HTML 标签和属性。

6. 正文渲染成了 markdown 源码

这个坑最折腾。页面渲染的是快照里的 content(HTML),不是 raw。如果通过 API 更新文章时只传 raw 而不传渲染好的 content,页面就会把 markdown 源码原样显示出来——图片全都变成 ![...](...) 的裸文本,表格变成 |---|。

正确的做法是:本地先把 markdown 渲染成 HTML,然后 raw(编辑用源)和 content(渲染后的 HTML)一起提交,再重新发布同步快照。而且验证时不能只数 /upload/*.jpg 的出现次数——源码里也有这些字符串,要数 <img> 标签才算数。

接口一览

后端挂在 http://<主机>:3000/api 下,主要接口如下:

用途 路径 说明
书签数据 GET / PUT /api/data 整份书签配置的读取与写回
备忘录 GET / PUT /api/notes 纯文本,落本地 JSON
提醒事项 GET / POST /api/reminders、DELETE /api/reminders/:id 增删查
文件 GET / POST /api/files、GET /api/files/:id/download、DELETE /api/files/:id 上传、下载、删除
天气 GET /api/weather 服务端拉取并缓存
热点新闻 GET /api/hot-news 顶栏信息流
虚拟化平台 GET /api/pve/status、GET /api/pve/vms、POST /api/pve/vm-action 状态、列表、开关机重启
平台配置 GET / POST /api/pve/config 密码只写不读
备份与恢复 POST /api/backup、GET /api/backups、POST /api/restore/:filename 本地备份
WebDAV 备份 POST /api/backup-webdav、GET /api/backups-webdav、POST /api/restore-webdav 异地备份
版本与更新 GET /api/version、GET /api/download-update 应用内检查更新
站点图标 GET /api/favicon、GET /api/favicon-cached 抓取并缓存 favicon
背景图 POST / DELETE /api/background-image 自定义背景
健康检查 GET /api/health 探活

安全设计

  • 服务只绑定内网,不暴露公网端口;
  • 所有密钥 / 密码只存服务端本地配置,前端一律不返回明文;
  • 整份数据支持一键导出,方便迁移与容灾;
  • 需要远程访问时走 WireGuard 回家,而不是把端口映射出去。

项目地址

https://gitea.zwbcc.cn/zwbpc/netnav

纯自用 + 兴趣项目,界面和数据都还在持续迭代。下一步想做的是把 NAS 存储水位、路由带宽也接进监控,以及多用户与基础权限。如果你也在捣鼓内网服务,欢迎交流。

记录于 2026-09-09,更新于 2026-09-10。