From 42ce31b1791983d81ba6bef5cc3e026790bad317 Mon Sep 17 00:00:00 2001 From: NowScott Date: Fri, 3 Apr 2026 16:24:58 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E4=BD=BF=E8=AE=BF=E9=97=AE=E9=87=8F?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E5=8A=9F=E8=83=BD=E5=8F=98=E4=B8=BA=E5=8F=AF?= =?UTF-8?q?=E9=80=89=EF=BC=8C=E7=BC=BA=E5=A4=B1=E9=85=8D=E7=BD=AE=E6=97=B6?= =?UTF-8?q?=E9=9D=99=E9=BB=98=E7=A6=81=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当 Turso 数据库环境变量缺失或数据库操作失败时,不再抛出 500 错误,而是将功能标记为禁用并返回正常响应。前端组件会据此隐藏访问量显示,避免影响页面正常渲染。在开发环境下保留警告日志以便调试。同时更新了 README 文档以说明此可选功能。 --- README.md | 7 +++++++ components/Footer.js | 18 ++++++++++-------- contexts/StatsContext.js | 19 ++++++++++++++++--- lib/turso.js | 5 ++++- pages/api/visit-count.js | 16 +++++++--------- 5 files changed, 44 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 48cb832..9c49046 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,12 @@ 接下来,进入Vercel部署,添加两个环境变量NOTION_TOKEN和DATABASE_ID。这些分别是从[我的集成][access-url]网站获得的密钥,以及您的Notion数据库的ID,当然也不要忘记给你的数据库连接集成。 +如果您还希望开启 **全站访问量统计** 功能(可选),请在 [Turso][turso-url] 创建一个免费的 LibSQL 数据库,并添加以下两个环境变量: +- `TURSO_DATABASE_URL`: 您的 Turso 数据库 URL +- `TURSO_AUTH_TOKEN`: 您的 Turso 数据库 Auth Token + +若未配置上述 Turso 变量,该功能将自动禁用,且不会对页面显示产生任何影响。 + 这样就完成了部署,可以尽情在notion数据库中添加你自己需要的网页。 ## 2.创建的目的 @@ -83,3 +89,4 @@ [notion-url]:https://nowscott.notion.site/aef09fbce63649cba8b9269374dbb641?v=36b6f2625b8e4e5faf9f68e1284bd2bc&pvs=74 [access-url]:https://www.notion.so/my-integrations +[turso-url]:https://turso.tech "Turso Database" diff --git a/components/Footer.js b/components/Footer.js index b1347cd..1cb9279 100644 --- a/components/Footer.js +++ b/components/Footer.js @@ -92,15 +92,17 @@ const Footer = () => { 投稿网页 -
- - 访问量: - - - + {stats.visitCount !== undefined && ( +
+ + 访问量: + + + + - -
+
+ )}
diff --git a/contexts/StatsContext.js b/contexts/StatsContext.js index 3774afd..92a2183 100644 --- a/contexts/StatsContext.js +++ b/contexts/StatsContext.js @@ -26,9 +26,18 @@ export const StatsProvider = ({ children }) => { try { // 每次刷新页面(即 StatsProvider 挂载时)都发送 POST 请求以增加访问量 const response = await fetch('/api/visit-count', { method: 'POST' }); - if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); + + if (!response.ok) { + console.warn(`[StatsContext] Visit count API returned status: ${response.status}`); + updateStats({ visitCount: undefined }); + return; + } const data = await response.json(); + if (data && data.enabled === false) { + updateStats({ visitCount: undefined }); + return; + } if (data && typeof data.count !== 'undefined') { updateStats({ visitCount: data.count }); } @@ -38,9 +47,13 @@ export const StatsProvider = ({ children }) => { try { const getRes = await fetch('/api/visit-count', { method: 'GET' }); const getData = await getRes.json(); - updateStats({ visitCount: getData.count }); + if (getData && getData.enabled === false) { + updateStats({ visitCount: undefined }); + } else { + updateStats({ visitCount: getData.count }); + } } catch (e) { - updateStats({ visitCount: 0 }); + updateStats({ visitCount: undefined }); } } }; diff --git a/lib/turso.js b/lib/turso.js index 43b9d04..69802a5 100644 --- a/lib/turso.js +++ b/lib/turso.js @@ -5,7 +5,10 @@ const url = process.env.TURSO_DATABASE_URL || process.env.indwebindex_TURSO_DATA const authToken = process.env.TURSO_AUTH_TOKEN || process.env.indwebindex_TURSO_AUTH_TOKEN; if (!url || !authToken) { - console.error('Turso configuration missing. Please check TURSO_DATABASE_URL and TURSO_AUTH_TOKEN in environment variables.'); + // 访问量功能是可选的,若缺失环境变量则静默退出 + if (process.env.NODE_ENV === 'development') { + console.warn('Turso configuration missing. Visit count feature will be disabled.'); + } } export const turso = createClient({ diff --git a/pages/api/visit-count.js b/pages/api/visit-count.js index 45b11e5..4690227 100644 --- a/pages/api/visit-count.js +++ b/pages/api/visit-count.js @@ -5,12 +5,10 @@ export default async function handler(req, res) { // 检查 Turso 客户端是否已配置 if (!process.env.TURSO_DATABASE_URL && !process.env.indwebindex_TURSO_DATABASE_URL) { - console.error('[API] Turso database URL missing in environment'); - return res.status(500).json({ error: 'Database configuration missing (URL)' }); + return res.status(200).json({ enabled: false, message: 'Turso database URL missing' }); } if (!process.env.TURSO_AUTH_TOKEN && !process.env.indwebindex_TURSO_AUTH_TOKEN) { - console.error('[API] Turso auth token missing in environment'); - return res.status(500).json({ error: 'Database configuration missing (Token)' }); + return res.status(200).json({ enabled: false, message: 'Turso auth token missing' }); } try { @@ -57,12 +55,12 @@ export default async function handler(req, res) { return res.status(405).end(`Method ${req.method} Not Allowed`); } catch (error) { console.error('[API] Error in visit-count (Turso):', error); - // 在生产环境提供更详细的错误原因 - const errorDetail = error.message || String(error); - return res.status(500).json({ + // 如果数据库执行报错,也将功能标记为禁用,避免前端报错 + return res.status(200).json({ + enabled: false, count: 0, - error: 'Internal Server Error', - detail: process.env.NODE_ENV === 'development' ? errorDetail : undefined + error: 'Database operation failed', + detail: process.env.NODE_ENV === 'development' ? error.message : undefined }); } } \ No newline at end of file From 3eb54c808808d1ce14dc455808354d6d419d79b1 Mon Sep 17 00:00:00 2001 From: NowScott Date: Fri, 3 Apr 2026 16:37:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=20README=20?= =?UTF-8?q?=E4=BB=A5=E6=8F=90=E4=BE=9B=E6=9B=B4=E6=B8=85=E6=99=B0=E7=9A=84?= =?UTF-8?q?=E4=BB=8B=E7=BB=8D=E4=B8=8E=E9=83=A8=E7=BD=B2=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将项目标题翻译为中文并添加副标题 - 重写项目背景、目的与迭代历史,使其更具故事性和吸引力 - 详细说明使用 Notion API 作为数据源的缘由和优势 - 优化“如何部署”部分的步骤描述,使其更清晰易懂 - 更新官方示例站点链接和联系信息 - 整体提升文档的叙事性和可读性 --- README.md | 97 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 9c49046..4bd9df7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Individual Web Index(网页索引) +# Individual Web Index (个人网页索引) [![GitHub stars][stars-image]][stars-url] [![GitHub forks][forks-image]][forks-url] @@ -6,66 +6,93 @@ [![commit-count-permonth][commit-image]][commit-url] [![contributors-count][contributors-image]][contributors-url] +> “在算法编织的迷雾中,找回数字生活里的那一枚‘锚点’。” -## 1.如何部署 +--- -在2024年5月21日的更新之后,部署这个项目变得更加简单。您只需要复制这个[Notion页面][notion-url]作为您自己的数据库,根据需要添加网站数据,然后fork这个仓库。 +在信息爆炸的今天,寻找特定、高质量的网站往往如同大海捞针。我们并不缺更多的搜索结果,缺的是一份属于自己的、精准的、可控的“数字指南”。 -接下来,进入Vercel部署,添加两个环境变量NOTION_TOKEN和DATABASE_ID。这些分别是从[我的集成][access-url]网站获得的密钥,以及您的Notion数据库的ID,当然也不要忘记给你的数据库连接集成。 +**Individual Web Index** 并不是一个复杂的工具。它更像是一份数字时代的“私人黄页”。它将 Notion 的灵活性与 Next.js 的高性能结合,为你打造一个极致、纯净的书签导航系统。 -如果您还希望开启 **全站访问量统计** 功能(可选),请在 [Turso][turso-url] 创建一个免费的 LibSQL 数据库,并添加以下两个环境变量: -- `TURSO_DATABASE_URL`: 您的 Turso 数据库 URL -- `TURSO_AUTH_TOKEN`: 您的 Turso 数据库 Auth Token +--- -若未配置上述 Turso 变量,该功能将自动禁用,且不会对页面显示产生任何影响。 +## 💡 为什么在 AI 时代,我们依然需要一份“黄页”? -这样就完成了部署,可以尽情在notion数据库中添加你自己需要的网页。 +很久以前,互联网初期有一种叫“黄页”的东西。它不依赖算法,只负责收录。随着搜索引擎的崛起,黄页逐渐淡出视野。 -## 2.创建的目的 +然而,在当下日益复杂的搜索环境下,结果的准确性往往被各种权重与广告消解。当你想要寻找那个曾经惊艳过你的小众工具,或者那个常读常新的技术博客时,搜索引擎并不总是那么可靠。 -很久以前,互联网初期有一个叫做黄页的网站,上面索引了许多其他网站。随着时间的推移,它逐渐演变成了搜索引擎。 +我仍然固执地认为,**每个人都需要一份属于自己的黄页**。 +- **它是私人定制的**:只收录你真正认可的、高频使用的网站。 +- **它是直观高效的**:包含标签分类与简短描述,让浏览与搜索不再是负担。 +- **它是毫秒级触达的**:支持全拼与简拼搜索,让你在指尖跳跃间,找到那个久违的页面。 -然而,在搜索引擎中,当涉及到寻找特定网站时,结果往往缺乏准确性。因此,我仍然认为每个人都需要自己的黄页。 +## ✨ 进化:从手动录入到云端数据库 -这个个人黄页将包含一系列经常使用的网站,以及添加标签和简短描述的功能,方便搜索和浏览。 +这个项目经历了漫长的迭代。 -最终,我决定将这个个人黄页命名为“个人网站索引”。 +起初,所有的网站数据都是我一行行手动输入到 JSON 文件里的。虽然那种“纯手工”的纯粹感让人着迷,但随着收藏的增加,维护成本也变得日益臃肿。每添加一个新站点,都意味着要打开编辑器、修改代码、重新部署……这种繁琐逐渐背离了“工具应服务于人”的初衷。 -## 3.网站迭代 +后来,我偶然在 B 站看到了一位 Up 主的分享:[用 Notion 当数据库写一个简单的 API][bilibili-url]。那一刻,我意识到 Notion 才是这个项目最完美的“后台”——它既有数据库的结构化,又有笔记软件的易用性。 -从我有这个想法到现在,这个网站经历了多次迭代,URL也变化了几次。当前并且是最终的网站是[nowscott.top](https://nowscott.top)。 +目前的 **v3.0.0** 版本,正式实现了这一构想。我们利用 Notion API 将数据彻底云端化,并配合全新的前端架构,实现了极致的访问速度。这意味着,我只需在手机或电脑的 Notion App 里随手一记,几秒钟后,我的个人黄页就会自动更新。 -在最新的 **v3.0.0** 版本中,我们进行了一次彻底的现代化重构。我们引入了 **Tailwind CSS v4**,重新设计了全站 UI,打造了极具现代感的“深海蓝”深色模式与高对比度的胶囊式布局,让信息的呈现更加高效且美观。 +在追求效率的同时,我们也没有忽略视觉的表达。我们引入了 **Tailwind CSS v4**,重新设计了全站 UI。深色模式下,那抹“深海蓝”不仅是为了视觉的舒适,更是为了在喧嚣的互联网中提供一丝静谧感。高对比度的胶囊式布局,让信息的呈现更加高效且美观。 -起初,数据文件是直接手动输入的。而在最新版本中,我们利用 Notion API 将数据存储在 Notion 的数据库中,并配合全新的前端架构实现了极致的访问速度。 +当前的官方站点也终于落定在:[0211120.xyz](https://0211120.xyz)。 -## 4.如何使用Notion API -(从Notion获取数据的代码未包含在此项目中。) +## 📓 关于 Notion API 的集成 -这个想法起源于Bilibili上一个上传者的视频,下面提供链接: +正如前面提到的,这个想法起源于 B 站 Up 主的启发。虽然项目本身专注于前端展示,但其核心驱动力来自于 Notion 的开放接口。 -[【S1E3】用Notion当数据库写一个简单的API](https://www.bilibili.com/video/BV1gF411E7pV/?share_source=copy_web&vd_source=98c7014c35363c157a4fba4929dbda77) +> **参考资源**:[【S1E3】用 Notion 当数据库写一个简单的 API][bilibili-url] -在这个视频中,我学习到了如何使用Notion API从Notion获取数据并在网页上显示。如果你有任何问题,可以观看视频了解更多信息。 +在这个视频中,我系统地学习了如何将 Notion 作为一个“无头数据库”(Headless CMS)来驱动网页内容。虽然从 Notion 获取数据的底层代码属于项目的“心脏”,但我更愿意分享这种将“笔记软件”转化为“数据引擎”的思维方式。 -总而言之,我利用 Notion API 从 Notion 获取数据并在前端展示。虽然 Notion API 本身响应时间可能较长,但我通过下文提到的优化手段彻底解决了这个问题。 +尽管 Notion API 的原生响应速度有时并不理想,但我通过下文提到的缓存机制彻底解决了这一瓶颈。 -## 5.一些优化 +## ⚡️ 速度与激情的“双层缓存” -我无法改变Notion API的访问速度,但我可以改变获取数据的方式。在 **v3.0.0** 中,我们实现了 **“双层缓存机制”**: +虽然 Notion API 让数据管理变得优雅,但它的原生响应速度一直是一个让人头疼的短板——有时甚至需要等待数秒才能返回结果。 -- **服务器端内存缓存**:通过在服务器端实现持久化的内存缓存,将原本 7-8 秒的 Notion API 延迟降低到了毫秒级(在开发模式和 Vercel ISR 中均生效)。 +**我无法改变 Notion API 的访问速度,但我可以改变获取数据的方式。** + +为了不让等待消磨掉寻找灵感的兴致,在 **v3.0.0** 中,我们实施了深度的技术优化,通过所谓的“双层缓存机制”彻底解决了这一瓶颈: + +- **服务器端内存缓存**:通过在服务器端实现持久化的内存缓存,我们将原本长达 7-8 秒的 Notion API 延迟降低到了**毫秒级**。这一优化在开发模式和 Vercel ISR 中均已生效,确保了数据的即时性与访问的高性能。 - **客户端状态管理 (StatsContext)**:利用 React Context 在页面间共享数据,实现主页与关于页之间的“无缝、无刷新”即时导航。 +- **🔍 智能搜索**:由 `tiny-pinyin` 驱动的拼音搜索功能。它支持中文名称与标签的全拼/简拼检索,让你能通过拼音快速定位到目标站点。 +- **🎨 自适应图标**:全新的动态 SVG Favicon。它能随系统主题颜色实时变换,在细节处保持视觉的绝对统一。 + +## 🚀 如何搭建你的数字指南针? + +自 2024 年 5 月 21 日起,部署这个项目变得像呼吸一样自然: + +1. **准备数据库**:复制这个 [Notion 页面模板][notion-url] 作为你自己的数据库,按需添加网站数据。 +2. **复刻仓库**:Fork 本仓库到你的 GitHub 账号。 +3. **Vercel 部署**: + - 添加环境变量 `NOTION_TOKEN`(来自 [我的集成][access-url])和 `DATABASE_ID`。 + - **别忘了**:在 Notion 页面中给你的数据库连接该集成,确保 API 能够正常调用。 + +### 📊 访问统计 (可选) +如果你还希望开启**全站访问量统计**,只需在 [Turso][turso-url] 创建一个免费数据库,并配置 `TURSO_DATABASE_URL` 与 `TURSO_AUTH_TOKEN`。若未配置,该功能将静默隐藏,绝不打扰。 -此外,我们还引入了: -- **智能搜索**:由 `tiny-pinyin` 驱动的拼音搜索功能,让你能通过拼音快速找到中文标签和网站。 -- **自适应图标**:全新的动态 SVG Favicon,能随主题颜色实时变换,保持视觉统一。 +--- -## 6.最后的说明 +## 📖 写在最后 -总之,这个项目是一个基于网络的个人网站索引,它通过深度优化解决了访问速度慢的问题,并确保了数据及时更新。这些优化使修改变得更加容易,并提供了更高效、无缝的用户体验。感谢您对这个项目的兴趣。 +这个项目是我对“个人数字空间”的一次小小探索。在今天这个信息过载的时代,拥有一个能够完全掌控、响应迅速且美感在线的个人书签系统,其实是一件挺奢侈的事情。 -如果您对这个项目有任何问题或询问,可以通过电子邮件联系我:[nowscott@qq.com](mailto:nowscott@qq.com) +**Individual Web Index** 并不是为了取代任何强大的工具,它只是为了在浩瀚的互联网海洋中,为你留下一处能够随时停靠的避风港。 + +如果你也曾为找不到那个收藏已久的网址而焦虑,或者厌倦了被搜索引擎牵着鼻子走,或许你可以试试搭建这份属于你自己的“网页索引”。愿这个小工具能像一阵清风,为你繁忙的数字生活带来一丝清爽。 + +感谢每一位关注这个项目的你。如果你有任何问题、想法,或者只是单纯地想聊聊关于数字生活的心得,欢迎通过以下方式找到我: + +- **Email**: [nowscott@qq.com](mailto:nowscott@qq.com) +- **示例站点**: [0211120.xyz](https://0211120.xyz) + +--- [![Star History Chart][stars-history-image]][stars-url] @@ -82,11 +109,11 @@ [contributors-url]:https://github.com/NowScott/IndWebIndex/graphs/contributors "贡献者" [contributors-image]:https://img.shields.io/github/contributors/NowScott/IndWebIndex -[web-url]:https://www.nowscott.top "中文网页" +[web-url]:https://0211120.xyz "官方示例" [web-image]:https://img.shields.io/badge/%E7%BD%91%E9%A1%B5%E9%A2%84%E8%A7%88-%E4%B8%AD%E6%96%87-blue [stars-history-image]:https://api.star-history.com/svg?repos=NowScott/IndWebIndex&type=Date [notion-url]:https://nowscott.notion.site/aef09fbce63649cba8b9269374dbb641?v=36b6f2625b8e4e5faf9f68e1284bd2bc&pvs=74 - [access-url]:https://www.notion.so/my-integrations [turso-url]:https://turso.tech "Turso Database" +[bilibili-url]:https://www.bilibili.com/video/BV1gF411E7pV/?share_source=copy_web&vd_source=98c7014c35363c157a4fba4929dbda77