阅读视图

发现新文章,点击刷新页面。

周报 #73 - 《社交网络》、Ego 与中秋的现充生活

《Photograph - Ed Sheeran》

前言

weekly_review_20240918

本篇是对 2024-09-092024-09-17 这周生活的记录与思考。

《社交网络》与 Ego

the_social_network

我和学姐从职业、爱好到性格都有非常多的不同,但并不是会相融的类型,因此常常也会去尝试或试图理解对方的 passion 所在,即使会常常发现更多的差异。

这周和学姐突然聊到为什么喜欢写代码,有时候这些动机和热情很难用只言片语来解释,突然想到几部影响我很深的电影/剧集,《The Social Network(社交网络)》、《Silicon Valley(硅谷)》等等,想到我订阅的 HBO MAX 已经好几个月没有打开了,于是趁着中秋假期一起看了《社交网络》。

大概是大学的时候我看了这部电影,后面的几年里又重温了几次,每次都能燃起我心中对代码与创造的热情,大概是由于把一个小小的想法实现为一个产品的奇妙历程总是让我着迷。

学姐提到 Mark 的自我中心、“渣”与背叛,或许天才或是成功的创业者或多或少有着自己的一些特质,但并不是必要成为一个“坏人”,好的秉性与好的技术/产品并不是那么水火不容,世俗意义上他成功了,但或许也失去了很多原本珍贵的东西。

在和学姐的闲聊讨论过程中我也发现了自己在其中 Ego 的部分,似乎「Code is law」的观念常常也会带来一些副作用,有足够的天赋或是写足够好的代码就会容易让人去忽视其中的自大、不尊重与不真诚的部分。

有时候这些观念也在侵蚀着我的日常生活,似乎 Coding 是极少的“仿佛”不需要合作就可以独立完成的事,也让我变得并不那么习惯于去合作,比如刚结束的 ETH Shenzhen 黑客松中我选择了自己一人队伍,很累,但似乎这于我而言是更为省力的一种模式,我似乎并不那么容易去信任他人,再深层一点我似乎并不觉得临时找几个队友能够做到什么我无法做到/学会的事,更严重一点也容易忽略他人的付出和贡献,尤其是非技术的部分,但有时候这还是挺糟糕的事。

正好公司内部很快就会举办一场为期一周的内部黑客松,我也会试着从中有意识地调整和观察自己在团队合作中的行为,也很期待一起做有意思的项目。

小小预告:和 Follow 有关。

中秋的现充生活

原本中秋想好好窝在家里写三天代码,但可能是由于前段时间总是睡前工作,精神和身体都有些许疲累,有点熬不动了,就趁着这几天好好休息调整了下。游了两天泳、去车库画了两天墙绘、第一次滑板上路、中秋回去家庭聚餐,现在的我现充得可怕。

似乎生活慢慢归于日常,多了很多似乎“无所事事”的时光,却也意外地珍贵。

car_garage_painting

想到今天在给墙绘画一块砖的时候,学姐说可以先近着描一些细节再走远了看一下整体,能够更好地把握画面。也看到墙绘从一开始到现在的对比图,看着墙面一点点增加细节(虽然我基本上是只是画了砖块),似乎也看到了生活的本质。

关于 RSS 的想法

上周我发起了一个选取邀请码的活动,原本只是因为邀请码稀缺而增加一些难度,但收到了很多评论,甚至总字数也远远超过了正文,能看到好多对于 RSS、阅读、信息处理的一些想法和探讨,发现 Remark42 可以订阅某篇文章的评论,我直接导入 RSS 链接 在 Follow 里看更新了。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。并且把 Telegram Channel 消息作为内容源搭建了一个微博客 —— 「daily.pseudoyu.com」,可以更方便浏览了。

收藏

书籍

文章

视频

周报 #72 - 滑板体验、Rust Conf 与 Follow 公测(含邀请码)

《Photograph - Ed Sheeran》

前言

weekly_review_20240908

本篇是对 2024-09-032024-09-08 这周生活的记录与思考。

去上海参加了 Rust Conf 2024,度过了两天,收获了很多周边,现场在同事的指导下重构我的用 Rust 写的 Api Server;Follow 进一步扩大了公测规模,要到了 10 个邀请码,会在本篇的评论区发放;还有很多有意思的事。

Lake 游戏

lake_pic_01

虽然团队的项目已经在上一周顺利上线了,似乎依然有不少需要忙的任务,工作时间偏晚,再加上早上要晨跑,工作状态和睡眠之间的界限比较模糊,有时候躺着很久都睡不着。持续了接近几天后,整个人有些提不起精神,于是决定晚上在 Lake 游戏中送送信放松一下。

lake_recommendation

好久之前就在 Randy 的一条推文了解到它,作为「Life is Strange 系列」这类游戏的爱好者,对于这种更生活化、平静却又引发思考的游戏一直很感兴趣。

如我在「周报 #70 - 消失的附近,Burnout 与 Boreout」中所说的那样,早早离开家乡的我现在也几乎没什么还在联系的童年玩伴了,小镇风景和我记忆里的村落当然也是天差地别,却依然被能够在各个小屋、邻居家亲切打招呼,倾听他们故事的感觉心生向往,或许这样的生活方式比起繁华的都市更加让人变得具体而知足。

不要问我一个程序员下班的时候还要扮演一个程序员下班/休假,我之前下班还玩「Shenzhen I/O」模拟程序员上班 🤡…

滑板体验课

我从小时候开始玩了十几年轮滑,几年前也曾学过一小阵子滑板,不过不算很系统,一直很想精进一下,后面也可以习惯滑板上路。

因为只是一小时的体验课,教练更多从滑行、放板、收板和转体的一些入门动作开始,纠正了挺多之前自己玩时候的不规范动作,慢慢也习惯了在板上的感觉。后面有两次因为想尝试下陡坡而狠狠摔了两跤,疼但却反而更有了一些运动后的压力释放感,也更感知到这一运动的魅力。

不过系统性的课程还挺贵的,可能考虑先自己再玩一阵子,10 月去清迈旅居的时候去找当地的教练学。

摔太惨就不放图了。

RSSHub 部署迁移

rsshub_hits

前几天因为不小心同步 OneDrive 和 iCloud 的时候用了自己 VPS 搭的代理,主力机器流量被刷完了,导致自建的 RSSHub 也停了。因为作为公益公开实例挂在 RSSHub 官网上,想着还是维护一下,于是转移到了另一台闲置的 2C2G 的机子上,发现机器瞬间被打爆了,看了下平均每分钟 100+ 次请求…

研究了一下发现 Zeabur 的模板没法通过 WebSocket 来访问 browserless/chrome 服务,现在用的镜像也并不内置 Puppeteer,很多网站没办法抓取,以至于很多路由失效,于是改了一下,发布了一个 Zeabur 模板,现在支持一键部署带 Puppeteer 的 RSSHub 实例了 —— 「RSSHub (With Puppeteer)」,欢迎一键部署。

然后自己部署了一份,也算是为 RSS 事业做贡献了。

Rust Conf

rust_conf_pics

这次没怎么拍照,偷了同事的周边图。

似乎每年都有那么一两个月会更“现充”地参与各种线下活动,和远程办公的同事/朋友们相聚。在参加完 ETHShenzhen 不久后,我又约了一些同事朋友来上海一起参加 Rust Conf,度过了有趣的两天一夜。

搜刮了一圈周边,去看了几个感兴趣的 Talk,和新老朋友浅聊一会儿,最后还是聚众在会场的一角 Review 和修改我写的 Rust 烂代码,学到了。

早上刚到就京东下单了一本「Rust 程序设计」,刚送到在酒店大厅开始学了…

个人生活剪影

偶遇的有趣设计

interesting_tre_huzhou

上周去湖州莫干山尝试了一下林间木屋,本身体验普普通通,但在返程时见到的一个有趣的大眼树却印象深刻,感觉在车窗的滤镜下有很日系。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。并且把 Telegram Channel 消息作为内容源搭建了一个微博客 —— 「daily.pseudoyu.com」,可以更方便浏览了。

书籍

文章

视频

音乐

Follow 公测特别活动

在之前的一篇「周报 #67 - 使用 follow 重塑我的信息输入系统」讲了我使用 Follow 这一应用的体验,依然十分惊艳。

一个多月过去了,依然是我每天都高频打开的软件,软件也迭代了不少新功能和亿点细节,慢慢也开始扩大公测规模了。

我向 DIYgod 要了 10 个邀请码来作为博客/频道读者的福利。

参与方式

在本篇文章下评论你关于阅读、信息流、RSS 使用或关于周报的相关想法,我会在北京时间 9.9 日 22:00 挑选 10 位发放邀请码,我会在评论区和 「Yu’s Life」 Telegram 频道公布名单,选中的用户可以联系 pseudoyu@connect.hku.hk 或任意我的社交平台私信。

活动后也可继续留言,如果我后续能拿到更多名额(或者我努力签到赚 Token),也会继续在评论区发放,欢迎参与。

周报 #71 - Indie App 体验计划

《Photograph - Ed Sheeran》

前言

weekly_review_20240903

本篇是对 2024-08-262024-09-02 这周生活的记录与思考。

这周我们团队做的去中心化索引正式主网上线,异常忙碌,输入输出和学习相较之前都少了不少;收到了 PaddingLeft 的贴纸;体验了 Xylect,想到一个好玩的计划;还有很多有意思的事。

RSS3 Node

rss3_node_epoch

这周我们团队忙碌了大半年的去中心化索引项目终于顺利上线 —— 「A New Era of Decentralized & Verifiable Data for AI & Open Web」。

理念和设计方面可以看白皮书 —— 「Whitepaper —— The de facto RSS3 Constitution.」。

有兴趣的朋友可以了解下。

更换贴纸

padding_left_03

Randy 的程序员周边品牌店上线了,见证了从他提到这个想法、到看厂家、再到正式上线售卖,执行力是真的强。

抢先体验成为了第一个下单的用户,刚好更换一批自己的贴纸。

padding_left_01

padding_left_02

在整理和更换贴纸的时候也发现慢慢成为了自己的记忆点。比如去 GopherChina 2023 拿了 JetBrains 官方的贴纸;去了 Rust Conf 2023 收获了很多小螃蟹;和同事去香港参加 Google AI 的会议拿到了 Google Cloud 贴纸,还在网吧枕着他们的周边抱枕度过了一晚。

突然有些理解手账的有意思之处,似乎能够通过这些痕迹来回顾自己去了哪些地方,又解锁了哪些新体验。

Indie App 体验计划

create_things_you_wish_existed

最近看到了一篇 laike9m 写的「推广独立开发产品,我做了哪些尝试」,讲了他推广 Xylect 这一划词 AI 搜索/翻译工具的历程。

自己其实也是早期 PopClip 的用户,后来也高强度使用 Bob、Haye.ai 等基于划词形态的产品,有些好奇,在官网看到有一条:

👨👩 Content creator? Contact me for collaboration and get free licenses

于是试着陈列了自己的 Twitter、TG Channel、博客、「GitHub - yu-tools」项目,发了邮件咨询了一下,很快得到了回复和 License 并加上了 TG 沟通,在使用过程中也提了不少用户侧的建议(有些已经在当前版本上线了),很新奇的体验。

文中有这样一句话:

开源项目永远是用户欠开发者,因为用户享用的是开发者的无偿劳动。而对独立开发(或者说所有的商业行为)而言,这种立场就完全逆转了。

自己一直很关注和向往独立开发,也试着自己开发过一些小产品,对于工具、效率类的开源项目和产品也常常第一时间去体验,时常有机会直接跟其开发者沟通,深知其困境。

而在和 WebP CloudXylect 开发者沟通的过程中,也发现我作为工具类产品的深度用户,时常也能从用户的角度提出一些小的建议,并通过文章(如「从零开始搭建你的免费图床系统(Cloudflare R2 + WebP Cloud + PicGo)」)呈现自己的真实使用体验和教程,常常也有开发者在我的博客评论下留言自荐项目。

于是萌生了一个想法,想着自己的周报和工具站「tools.pseudoyu.com」新增一个 Indie App 体验计划的模块,去体验自己觉得很棒的产品,会尽可能结合开发者和用户两个视角来给出自己的真实体验和使用方式,感觉会很有意思。

我并不是一个体量很大的 Infulencer,只是通过文字传达自己生活、思考和体验的内容创作者,并不一定能为产品带来多少用户或是付费转化,但我依然觉得好的产品值得被看见,哪怕只是增加了一点点。

我会从自己日常使用的产品开始,标准想引用之前看到的这句话:

Create the things you wish existed.

当然也欢迎通过 pseudoyu@connect.hku.hk 自荐~

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。并且把 Telegram Channel 消息作为内容源搭建了一个微博客 —— 「daily.pseudoyu.com」,可以更方便浏览了。

收藏

播客

书籍

文章

视频

音乐

周报 #70 - 消失的附近,Burnout 与 Boreout

《Photograph - Ed Sheeran》

前言

weekly_review_20240901

本篇是对 2024-08-192024-08-25 这周生活的记录与思考。

消失的附近

disappear_neighbor

大概由于童年有七八年都是在老家长大,刚搬来杭州时候我所在的社区也有一群年龄相仿的玩伴,我大抵还算是一个“野孩子”。

在老家时候就不用说了,爬树、抓知了、下河摸鱼,折几枝柳树藤蔓自己做弓箭或是削弹弓,天地广阔,似乎总能有自己的乐趣。即使是到了杭州后,小时候每次吃完晚饭最期待的都是出去街道喊一声,会有人一起玩轮滑、滑板,会走街串巷地闲逛,也会去“富有”的朋友家里看他玩口袋妖怪(现在的「宝可梦」)。

而不知是自己年龄渐长还是整个城市变了,似乎现在鲜有“邻居”和“社区”的概念,总是一家一户一生活,甚至对家附近有哪些店、发生了哪些事也一无所知。

少年意气风发时候的自己自然是不甚在意,有很多同学、朋友,每次约出门也都是在繁华闹市街区,生活的“附近”太小,装不下自己的多彩生活。

然而,离开校园后的这几年的感受会更明显一些,即使生活确实显而易见地比之前丰富得多了,内心的孤独感却日渐增加。许多朋友渐行渐远,大家都有了新的工作、生活甚至是家庭,有时常常连开心或是难过的情绪都一时不知该向谁说。

还想起有一次在北京和渐仔相约打羽毛球,也一起吃了个晚饭,我们在合生汇看到了一个街机游戏厅,一起打了一个多小时的「三国志」,现在的我们已经可以不太在意花了多少游戏币,能不能打到通关,似乎只是想从中找回少年时的快乐。

可是却再也找不到了。

今年开始更频繁地去良渚和朋友一起办公,即使逾半小时的车程有些折腾,杭州夏日扑面而来的热浪也令人却步,在这每周难得的体验中似乎能够重新获得一些生活的能量和图中所说的对“附近”的感知能力。

Burnout 与 Boreout

前几周的某个周末,同事突然来问我最近状态怎么样,是不是发生什么事了。我起初有些诧异,其实自己感觉一切还算正常,详细聊了下后,才发现是自己的感知和实际的感知之间存在一些偏差,刚好也看到了这篇文章 —— 「Is it burnout or boreout?」,于是仔细回顾了一下这几个月的状态。

Burnout

总是有一些朋友会问我说是不是同时做的事太多了,但其实我自知并没有,甚至内心深处还是会焦虑自己做得依然不够多不够好。大概是“冒名顶替综合征”的影响,我总是觉得自己并不如同事朋友们那般有天赋与创造力,我似乎总是需要额外做一些事来填补内心的这种“不配得感”。

因此自大学来我一直以来都有“多线程”的倾向,在刚毕业职业发展的前期其实这种倾向给我带来了不少好处,我似乎成为了那个别人口中的“卷王”,总是在职责范围内做更多,学更多,也因此取得了许多不错的成果。

然而现在从实习开始算起的话,工作已经三年有余了,随着自己的能力刚刚好能满足工作的需求却有时候似乎难以有一些创新的时候,自己陷入了一种痛苦的“Burning Out”状态,一种职业的倦怠感,似乎有着一些工作量,但其实远远没有达到自己的承受范围或是极限,但有时候会让焦虑和自我怀疑包裹着自己的工作时间:

这个实现方案正确么?

我是不是应该在这个基础上做更多的优化,但似乎还没什么好的思路?

似乎同事都能够 handle 好自己的部分,我是不是应该更主动一点找到自己的定位?

这种 Burnout 的状态很狡猾,并不会让自己倦于工作本身,而是隐藏在工作量之下,所以自己甚至不太容易感知到,倦怠本身是一种情绪,让我缺少足够的能量去应付,同时会侵蚀自己的目标感和控制感,造成拖延和一些任务的错漏,然后加重自我怀疑。

Boreout

工作的前两年其实一切都是新的,工作任务和技术学习所带来的正反馈和刺激感很强,而现在工作任务只要付诸时间基本上能够独立或和同事的协作下完成,但由于工作内容相对稳定了,一项项 checklist 打钩所带来的满足感远远比不上学习一门新语言或是新框架,自己似乎又陷入了一种“Boreout”,对自己所做的工作内容以及自己所能为这份工作贡献的价值产生了怀疑。

以同事聊到工作状态之后这两周正视了这一问题,感觉产生了一些效果,恰好也对应文章中给出的几种解决方案。

Align

当时选择参加现在的公司和项目时,更多是由于其氛围和价值观,一年多过去了,其实原本的理由犹在,外力并不是造成自己状态改变的理由,应该更多向内探索。

Brainstorm

自己其实算不上什么独狼的性格,只是确实常常有些难以做到去麻烦别人,再加上有些 i 的性格,在群组讨论中似乎更多还是听从者的角色,参与感的缺失有时候也是自我怀疑的来源,像是和同事聊聊自己的问题,或是线下一起办公、参加活动,似乎能够更多汲取热情和能量。

Experiment

尝试在工作方式上做一些小的改变而不是因循原有线性的模式,并不每次都把“创新”作为唯一目标(往往会因无法达到而产生挫败感),有时候仅仅是一些方式的改变,在技术调研时的多几分探索,似乎就已经足够产生一些改变了。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。并且把 Telegram Channel 消息作为内容源搭建了一个微博客 —— 「daily.pseudoyu.com」,可以更方便浏览了。

收藏

书籍

文章

视频

周报 #69 - AI Coding 体验与学习的源动力

《Photograph - Ed Sheeran》

前言

weekly_review_20240819

本篇是对 2024-08-122024-08-18 这周生活的记录与思考。

从 VS Code 转向 Cursor 写代码,聊聊 AI 加持下的编程体验;和学姐在一起 400 天;某天和学姐有了关于过去经历和兴趣爱好的一次深夜长谈,引发了我对自己的学习源动力思考;还有很多有意思的事。

AI 加持下的编程体验

cursor_screenshot

这两周高强度使用了 Cursor,一个基于 VS Code 的 AI IDE,效果很惊叹。

我其实算是 GitHub Copilot 的非常非常早期的内测用户,直到现在也还在用;而在 ChatGPT、Perplexity、Devv.ai 和 Claude 出现后也都是高强度的付费用户,思维上已经很习惯使用 AI 来帮我写代码了,但是更多还是补全部分逻辑和调试 Bug,没办法做到项目级的辅助。

而在 Cursor 把整个项目作为上下文、提问时可以 @ 其他文件或代码、并且使用 Claude 3.5 Sonnet 模型之后,体验感和可用性已经和我想象的形态越来越近了。

web3insights_demo

实践上,在试用 Pro 的 15 天中,解决了我工作中的 Go 的一些 Bug 修复和新增 Tests;改进了 Electron 应用的一个更新提示界面和功能;从零开始帮助我写了一个 rust 的后端 CRUD api 包括完整的 Dockerfile 和 GitHub Action 部分;帮助我完成了一个 Remix 项目的数据可视化部分以及很多个界面的调整,精确到各个页面之间的交互和布局;以及顺便还帮我学了一些 SwiftUI。

我大概已经有 50% 以上的代码是在 AI 辅助下甚至直接 AI 生成的了,而我更多的时间都是「CMD + K」(Cursor 的代码生成快捷键)的对话框中跟 AI 沟通需求,在梳理 prompts(大部分就是按照对话自然语言来表述),对话或是等待代码生成的时候反而有了更多时间去思考代码架构、逻辑、更合适的第三方库等。

其实让 AI 了解我的需求的时候,自己也在反复思考其合理性,反而能产出功能和代码质量都更优的代码,至于语法和代码风格方面,我常常直接去研读和学习 AI 的实现,比起从零开始去读一个开源项目要好上手得多。

而我需要做的,就是设计和创造。

正如 Randy 在 「代码艺术家」不会被 AI 取代 一文中所引用的:

I realize the reason I like building is not just because I’m a builder.

我意识到我一直喜欢创造点东西的原因不只是因为我就是个创造者.

It’s because software products are how I express my creativity.

而是因为写软件产品是我表达我的创意的一种方式

It’s like a poem to a poet, a song to a songwriter, a painting to a painter…

就像诗人的诗,歌手的歌,画家的画

Software is my art form, my medium of expression.

软件是属于我的一种艺术形式,是我表达(创造力)的媒介。

ETHShenzhen Hackathon

web3insights_ethshenzhen_demo

上文提到的项目是我周末在深圳参加的活动,其实算是自己正经作为选手参加的第一个 Hackathon 活动,通宵两晚写完了 Demo,在现场写了基础的演讲大纲和几张简略的 PPT,最后完成了 Demo 演讲,比想象的还是要累不少,周日才睡上一个好觉。

学习的源动力

有一天晚上从给我妹妹选滑板开启了话题,和学姐夜谈到了过去的一些经历,以及自己的各种兴趣爱好。

我的奇奇怪怪的技能树和兴趣爱好其实不算少。学生时期大大小小的运动至少都接触过,大部分也还算上手;小时候也用那种扭扭的滑板四处刷街;轮滑自小学开始到大学参加轮滑社坚持了接近十年;跟着我表哥一起去游泳馆玩,自然地学会了游泳;大学后玩了摄影、学了剪辑,在全校飞无人机,也成立了工作室从各种灯光布景都研究了下;做过审计的实习、甚至因为创业开公司而自己把注册公司、财务报税、开发票、企业清缴汇算申报以及注销流程在没有中介和财务的帮助下自己操作了近两年;工作中也是对各种编程语言框架都很好奇,算是经常尝鲜。

我似乎一直有这样野路子学习的倾向,以及在学到了恰好足够满足我当时的需要时就戛然而止,并没有更多的欲望去深耕其中。例如,我算是喜欢摄影,甚至在做摄影和视频相关工作室创业的时候也有过把它作为自己事业的念头,但那么多年其实我似乎并没有真正地从构图、光影、色彩、修图这些去系统学过,视频拍摄剪辑也没有从戏剧理论、导演思维这一块打基础,只是在需要用的某个技巧或是功能的时候再去快速学习,够用但也仅仅是够用。

我认真剖析了自己的内心,发现了很有意思的现象,还会追溯到童年甚至更小的时候。

我很小的时候转学来到杭州,其实花了很多时间来让自己讲话不带乡音、以及花了好几年成绩才慢慢达到中上,也经历过一些带着歧视或是不公,内心积累了不少自卑的部分。而随着初中遇到了很好的老师,生活和学业才慢慢走上正轨。

这时候其实多了另一种评价,“你做到 xxx 一定很努力吧”

我并不是否认“努力”的重要性,只是常常被那么说,总觉得有些挫败,似乎连我自己都觉得,我就是不如别人,只是很努力,所以比别人取得了更多的收获,陷入 Impostor syndrome (冒名顶替综合征) 的自我恶性循环。

于是我慢慢开始不那么“努力”,似乎在向他人和自己证明,我能“轻易”做到这些事,渐渐地,也享受其中。

带给我快乐的常常并不是学到的知识或运用它实现什么,而是“学习一个新东西”和“我能够很快学会它”这样的心理正反馈。这带给了我一些好处,如长期这样乱点技能树积攒的信心让我面对新事物或许多看似遥远的目标时不会那么畏惧 ——

“过去的我做到那么多了,现在的我一定也能”。

但也让我有时候并没办法沉下心做好一件事,或者把某项真正喜欢的事做到最好,有广度而缺深度,感觉也是一种 trade off,慢慢也开始有一些改变。

个人生活剪影

400 天纪念日

love_record_400

和学姐 400 天了。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。并且把 Telegram Channel 消息作为内容源搭建了一个微博客 —— 「daily.pseudoyu.com」,可以更方便浏览了。

收藏

播客

文章

视频

周报 #68 - 关于写博客这件事与我生活的色彩

《Photograph - Ed Sheeran》

前言

weekly_review_20240811

本篇是对 2024-08-052024-08-11 这周生活的记录与思考。

从 TG Channel 里回顾了一下这周,发现一整周都围绕着搭博客和写博客这两件事,有了一些思考与分享欲,大部分内容都发过,算是一个整理了。

写博客的 ROI

blog_roi_x_discussion

前几天在推特上看到了关于写博客的一些讨论,又看到 Innei 的这篇「从讨厌写作到乐于分享:我与写博客的心路历程」,很有意思,于是趁机仔细回顾了一下整个写博客的历程与收获。

最后得出一个个人的结论是,我也觉得写博客是一件成本不低、周期长但 ROI 非常高的事。

如果按照广义的发自本心的写作来说,从高中左右就开始写散文、公众号、博客等等,持续了接近 10 年了,真正直接从为自己写的文字赚到的收入大概只有少数派发的六七篇上了首页的文章共计 3000 元左右稿费和一位读者坚持了一年多了依然还在每个月给我 GitHub Sponsor 的 5 刀赞助。

一开始就有心理预期,脱离了公司的薪酬外,不管是做产品还是写文字,哪怕让用户/读者为你付一美元都是一件并不容易做到的事,但就像 Randy 在 Notepal 的一篇文章里说的,「有人愿意购买」的意义远比数目的大小更大。

写博客也带来了非常多潜在的意义和回报。我去年来现在的公司面试时,一位当时的面试官现在的同事就有说,全组在面试前都有看过我的周报,对我的性格、技术力和学习能力等已经有了一些初步的了解了;在社交媒体上,也通过文字让我和许多我非常崇拜的人有了更多更深度的交流甚至是合作;在许多线下活动做了简单自我介绍后,也常常能听到一句“哦,我看过你周报,很喜欢”。

这些都是并不以此为目的但在长期的坚持中收获的惊喜。

而不论是写博客还是其他形式的创作,似乎都有着相似的路径。起初新鲜而动力十足;逐渐在漫长的周期中消磨信心,看到别的好的文章/作品感受到的不是美好而是压力 —— “为什么我写不出来”;慢慢沉淀回归自我,恣意、快乐,享受其中。

我生活的色彩

colored_camera

想起来在刚写周报的时候由于读了村上的一本小说而写的「周报 #09 - 没有色彩的 Yu 和他的巡礼之年」,里面我这样写道:

多崎作所在的小群体中其他四人以及后续结交的挚友的名字都巧合地包含了颜色词:“赤”、“青”、“黑”、“白”、“灰”,让他感觉自己就像是一个没有个性的存在,连带着没有色彩的人生。

其实关于自己名字的埋怨常常有,『请回答 1988』里德善也有向父母埋怨自己的名字毫无特色,不如姐姐宝拉。我也曾有过这样的想法,似乎自己的名字简短而没有特色,再加上也是几个大姓之一,常常在一个学校遇到不少同名的人,与之相伴的就是自己常常也需要额外努力才能留下更多记忆点。

虽然后续也和自己和解了,但似乎还总是感觉自己的生活与有趣已经无缘了。总是羡慕别人的有趣个性和经历,也常常在即使自己做得不错时也只是觉得在履行自己平凡人生的职责或是这些都并不属于自己。

就这样平凡的我常常也会犹疑,自己的生活“流水账”是否有这样的价值呈现在所有人的面前,直到最近恰好在 B 站上看到这样一个视频 —— 「什么是好看的色彩?拍视频五年,我调色成了什么样」,是讲调色相关的,里面的一句话却深深打动了我:

当我第一次把镜头对向自己的时候,我才发现拍得可以那么惬意,没有压力。这时我才发现,我以前羡慕的不是那个画面,而是背后浪漫热烈的生活,这是我爱折腾的意义,我想让你看到我眼里的世界,而我屏幕里最好看的颜色,就是我生活的底色。

这是对我现在写周报时的心境最恰如其分的形容。

博客搭建系列

博客搭建系列终于更新完了!前后加起来也有 10 篇之多,自己也算是入围博客装修赛道的了。

从一开始 Vercel 部署都不太会用,到现在市面上的 Serverless 几乎都玩过一圈了,很有意思的体验,一切都按照想法运作的体验真的很美妙,搭博客和写博客确实各有乐趣。

2024 版

比起两年前其实发布流程与外观几乎没什么变化,但组件和内容却已经很不一样了。

2022 版

除了平台有些变化,很多不再提供 Free Plan 外,流程基本都依然适用的。

不知道下一次更新这个系列的时候,自己会在做些什么,又在想些什么呢。

多语言支持

en_version_blog

其实我的博客一直是有双语的功能选项的(导航栏可以全站切换/文章中也可以直接点击对应语言切换),只是一直很偷懒所以只是把中文文档复制过去,今天早上通过 Claude 的 Projects 功能把现存所有文章都翻译了。

新建了一个 Blog Translation 的 Project,输入一个全局 Instruction,之后就把 Hugo 的 markdown 源文件丢进去就可以了。

模型使用的是 Claude 3.5 Sonnet,为了节省上下文,我每篇文章开了一个新的对话,发现一百三十多篇文章都翻译完了居然还没触发 Claude Pro 的 usage limit(在 9:40 am 的时候提醒了一下 10 am 前只剩 10 条,之后再也没有出现过),有点良心。

因为我今天的目的主要是完成所有文章的转换和粗校,后续内容上的还是会人工去校对一下,所以用的 Prompt 比较简单,不过返回格式的可用性和翻译质量都超乎想象。

You will receive a Chinese blog post in Markdown format (.md) using the Hugo template. Translate the content into English, adhering to the following guidelines:

  1. Use a literary tone for posts in the “Idea” category; otherwise, employ a professional tone.
  2. Maintain consistent terminology, especially for structural elements like “preface” and “conclusion”.
  3. Preserve all Markdown formatting and metadata, including Hugo properties, links, audio, images, and other elements.
  4. Translate only the blog content itself.
  5. Return the result in Markdown format for easy copying.
  6. Do not add any introductory statements, explanations, or additional content to the blog.
  7. Provide only the raw translated Markdown content in your response.

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。并且把 Telegram Channel 消息作为内容源搭建了一个微博客 —— 「daily.pseudoyu.com」,可以更方便浏览了。

书籍

播客

文章

视频

电影

  • 生活多美好,久违的看到流泪的片子。跟《土拨鼠之日》一样,看完会重拾一些对生活的热情与周遭 relationship 的思考;也不需要多么精致的画面或是置景,演员的眼神似乎都是亮的,透着灵性,这大概也是老电影的魅力。

使用 GoatCounter 与 Zeabur 搭建网站数据统计系统

前言

在「2024 年了,我的博客有了什么变化」一文中,我介绍了自己使用 Serverless 平台和一些开源项目搭建的博客系统,也开启了这个系列教程来记录搭建和部署全过程。

本篇是关于统计系统的解决方案。

统计系统方案

相比起博客本体和评论系统,我在很长的一段时间其实都没有在意过统计系统(主要当时也没人看),更加没考虑太多 SEO 或是什么其他推广方向上的事,但后来逐渐发现,其实统计下来的数据并不只是一张好看的可以用来发推的图表,其对于博客的选题、内容都有着很大的参考价值。

其实主流成熟的方案都能够满足基本的需求,即使是免费的 Google Analytics 也完全够用,但在博客发展过程中,我依然因各种原因有过几次迭代,最终使用了 GoatCounter 这一方案。

splitbee

我最初使用的是一个免费的工具 splitbee,它提供了免费的基础统计额度,有着还不错的界面,并且还支持一些复杂的用户追踪,A/B test 等,但印象里好像只能保留半年的数据,并且每月超过 5000 pv 后就需要升级了,所以后来放弃了。

Cloudflare + Google Search Console

cloudflare_web_stats

放弃 splitbee 之后,很长一段时间我没有集成额外的统计应用,而是用的 Cloudflare 自带的站点统计,但是发现它其实统计的只是网络总流量,有包括爬虫在内的非常多的无效数据,并且没有精确到路径等细节。

google_search_console

后来了解到了 SEO 这一概念后,又添加了 Google Search Console 这一统计维度,这也是目前觉得对我写博文最有意义的数据,主要呈现的是用户在搜索引擎中触达我博客站点的关键词以及通过搜索点击进入我博客的页面路径。

可以看到,一篇「Warp,iTerm2 还是 Alacritty?我的终端折腾小记」为我带来了许多访客,而关于博客搭建、智能合约开发也是大部分从搜索引擎来的自然用户对我博客的第一印象。

Umami + Supabase + Netlify

yu_umami_record

但是上述两者依然只能看到网站整体的数据,想精确到某篇文章在一段时间的表现或者文章发布后的实时访问数据,依然需要一个统计系统,我在看了 Reorx 的一篇「搭建 umami 收集个人网站统计数据 | Reorx’s Forge」选择使用了 umami 这一开源、易自部署的统计系统,界面简洁,功能易用,很方便集成到自己的博客系统中。

使用了一年半,一直倒没出现什么问题,,只不过可能因为自己用得比较早,在一次大版本更新的时候数据库 Migration 脚本出现了不兼容的字段更新,其实有点不理解这样量级的开源项目为什么会出现这样的问题,也看到 issue 中有很多其他用户有同样的诉求,但最终并没有给出一个比较好的解决方案。

但其实最大的问题是一个统计系统依赖了两个平台,部署和维护上都还是有些太重了。当数据库或是 Netlify 任一出现问题或需要迁移时,会带来许多额外的成本。于是前段时间在更新博客评论系统的时候,想着干脆就一起更换为更轻量的 GoatCounter。

GoatCounter + Zeabur

goatcounter_stats

这个小众的统计系统是我在看 Reorx 的博客代码更新的时候偶然发现的,一下子被这种 Retro Internet 的风格所吸引,几乎没有任何多余的按钮,功能却很完备,而且使用的是 go 单二进制文件 + sqlite 数据库单文件的架构,轻量而易于部署,于是打算迁移。

其实我自己的 GoatCounter 是部署在 fly.io 上的,但我在上一篇 Remark42 的文章中已经非常详细地介绍了 fly 的操作说明,不想有太多重复,刚好最近又在重度使用 Zeabur 这一 Serverless 平台,于是本文将以 Zeabur 为例,方式同样适用于其他类似平台。

我也在下文的 Zeabur 部署方案之后提供了 fly.io 和在 VPS 上使用 docker-compose 部署的配置文件,供大家参考。

GoatCounter 部署说明

GoatCounter 本身代码开源 —— 「GitHub - arp242/goatcounter」,文档清晰易读,可以根据自己的实际需求进行配置。GoatCounter + Zeabur 的方案仅牵扯到单个服务,数据库使用的是 sqlite 挂载于 volume 中,所以部署起来非常简单。

使用 Zeabur 部署

Zeabur 对于容器应用的部署是需要 Developer Plan 的,5 美元/月,但是像这样的镜像服务整体用量和费用都较低,每月的额度足够部署非常多服务,可以酌情选择。整体部署流程比起 fly.io 简单很多,所有操作都可以使用 Web 界面完成,不需要额外安装命令行工具等。

注册 zeabur

zeabur_login

访问 Zeabur 官网,并点击右上角,使用 GitHub 账号授权登录。

创建新项目

zeabur_new_project

进入主界面后,点击右上角 创建项目 按钮。

zeabur_hk_region

我选择了香港的 AWS 机房,不同机房的访问速度、性能和价格会有一些差异,可以根据自己的需求进行选择。

配置镜像部署

zeabur_build

在下一步中选择 Docker 容器镜像进行部署。

zeabur_docker_custom_config

由于我们使用的是自己构建的镜像,官方也没有上线 GoatCounter 模板,因此我们点击选择自定义。

zeabur_prebuilt_edit_toml

这一步可以自己在界面上填写各种配置项,但可能由于我习惯了 fly.io 的文件配置模式,我选择左下角的 编辑 TOML 文件,大家也可以直接复制我的配置文件并直接修改。

name = "yu-goatcounter"

[source]
image = "pseudoyu/goatcounter"

[[ports]]
id = "web"
port = 8080
type = "HTTP"

[[volumes]]
id = "goatcounter-data"
dir = "/data"

[env]
PORT = { default = "8080" , expose = true }
GOATCOUNTER_DB = { default = "sqlite3://data/goatcounter.sqlite3" , expose = true }

zeabur_prebuilt_goatcounter_toml

配置好后点击右下角部署按钮即可。

部署完成

yu-goatcounter_project

点击部署后,等待片刻,会有一个生成的项目默认名称,可以在左上角的设置中去修改为可读性较强的名称,如 yu-goatcounter

配置自定义域名

zeabur_create_domain

服务部署完成后,我们需要进行域名绑定才能通过公网访问网站,Zeabur 提供了免费的二级域名 xx.zeabur.app,也可以绑定自己的域名。

zeabur_custom_domain

其中生成域名可直接使用,无须进行其他配置,如 goatcounter.zeabur.app;而如果使用的是自定义域名,则需要在自己域名管理后台添加 CNAME 记录,指向格式为 xxx.cname.zeabur-dns.com 的机房地址。

cloudflare_goatcounter_config

例如我的域名托管在 Cloudflare 上,添加的 CNAME 记录如上图所示,有去问过官方,说如果选 AWS HK 机房的话可以不使用 Cloudflare 的代理,速度理论上会更快,可以根据自己的需要酌情配置。

此外,如果你选择的是华为云机房,则需要域名备案并且额外新增一条 TXT 记录,可以根据提示进行操作。

zeabur_custom_domain_success

显示绿色则为配置成功,至此我们的 GoatCounter 服务就部署完成了。

数据备份

我们在配置时候有这么一段

[[volumes]]
id = "goatcounter-data"
dir = "/data"

功能是将容器内的 /data 目录(即我们的 sqlite 数据库存在的位置)挂载到一个 id 为 goatcounter-data 的存储卷,如果不挂载存储卷的话,容器重启或重新部署数据将会丢失。

关于存储卷这一点 Zeabur 的界面上没有很直观的显示和管理操作,以至于我总是怀疑自己的配置是否生效。

zeabur_add_goatcounter_backup

研究了半天发现可以先在设置中暂停服务,然后在上面的备份模块新增一个备份,点击下载后可以在本地看到我们备份文件,目录层级如下:

data/
└── goatcounter-data
    └── goatcounter.sqlite3

这样则能表示我们的数据成功持久化了,希望 Zeabur 能在界面上有更直观的显示。

使用 fly.io 部署

纯免费的方案依然可以参照我提到的这篇「从零开始搭建你的免费博客评论系统(Remark42 + fly.io)」,仅在 fly.toml 配置部分不同,我也提供的我所使用的配置文件 —— 「fly.toml」供大家参考。

使用 Docker 与 docker-compose 部署

有意思的是,因为 goatcounter 的作者很有坚持,觉得这样单文件的应用容器化反而会增加更多维护成本,所以不提供官方镜像,不过自己在 vps 或者 serverless 平台部署有个镜像还是方便一些,所以我使用 Github Actions 做了一个构建镜像和上传 Docker Hub 的 CI,有需要的可以使用,对应的 Dockerfile 和 Docker Compose 文件也可以参照这个 Commit,或者直接使用 pseudoyu/goatcounterdocker-compose.yml 文件即可。

version: '3'

services:
  goatcounter:
    image: pseudoyu/goatcounter
    ports:
      - 8080:8080
    environment:
      - PORT=8080
      - GOATCOUNTER_DB=sqlite3://data/goatcounter.sqlite3
    volumes:
      - ./data:/data
    restart: unless-stopped

GoatCounter 配置说明

上文我们完成了 GoatCounter 服务的部署,现在就可以通过我们生成/自定义的域名访问到我们的统计系统服务了,如我是通过 https://goatcounter.pseudoyu.com 进行访问的。

goatcounter_create_user

第一次登录需要创建一个用户,填写邮箱、密码点击 Create 即可。

goatcounter_dashboard_success

登录成功后,当前还没有数据,会提示一个脚本,后续在我们博客使用的配置中会用到。

博客配置 GoatCounter

跟着上文我们完成了 GoatCounter 服务的部署和基础配置,现在则需要在我们的博文中加入统计组件,以我使用的 Hugo 博客为例。

<script data-goatcounter="https://goatcounter.pseudoyu.com/count"
        async src="//goatcounter.pseudoyu.com/count.js"></script>

add_goatcounter_script_in_hugo

将上述代码加到我 hugo 主题的 head 中即可,如我的 Hugo 主题在 layouts/partials/head.html 这一文件,不同主题或是不同 SSG 框架位置有所不同但大同小异。

有一点要注意的是, goatcounter 会忽略来自 localhost 的请求以避免在本地预览时造成太多脏数据,因此在本地调试时是看不到数据的,需要部署网页才能看到访问数据。

final_display_of_goatcounter

收集了数据后的效果大致如上图所示,还可以在 GoatCounter 界面中设置一些配置项、新增网页、查看详细数据等,包括还可以显示每个页面的访问计数等,可以自己根据文档进行探索。

总结

至此我们的博客统计系统就搭建完成了!本文是我的博客搭建部署系列教程之一,博客主题体部分都已经完成了,剩下只是一些例如博客内搜索等细节体验优化,希望能对大家有所参考。

周报 #67 - 使用 follow 重塑我的信息输入系统

《Photograph - Ed Sheeran》

前言

weekly_review_20240805

本篇是对 2024-07-312024-08-04 这周生活的记录与思考。

这一周最开心的是体验到了 follow,久违的一款让我有兴奋感的应用,对比了 Readwise,并决定退掉订阅;做了一套自部署的 Web Archive 方案,eat your own dog food 的感觉真好;继续和学姐一起做墙绘;还有很多有意思的事。

使用 follow 重塑我的信息输入系统

我的信息输入系统

很久之前自己其实是一个信息重度依赖者,遇到好的博客/资讯网站,迅速加到 RSS 订阅源中,看着分类/标签井然有序的列表傻乐;遇到好的 newsletter,也马上用邮箱订阅;每天早上第一件事就是把当时还在用的 Reeder 4 未读清空,再将 newsletter 中的邮件一条条浏览。

起初其实还行,似乎自己关心的一些资讯和文章都能第一时间读到,有一种满足感,但逐渐就有些过载了,每天早上花在上面的时间越来越多,即使并不感兴趣的文章也会花费一些时间去消化,与其说是获取信息,倒不如说是一种信息渴求和对信息焦虑的代偿,效果自然是有的,信息都在大脑中留下了痕迹,但消化效率并不高。

在阅读了「使用自动化工作流聚合信息摄入和输出」和「对 Newsletter 说不」这两篇文章后,我做出了很大的调整。

信息源方面,我退订了所有公众号和 newsletter,并将 RSS 订阅源缩减到 50 个左右,剩下的大部分输入都来自于 Twitter、他人的 Telegram 频道等,在把输入控制在一定量级的同时一定程度上避免信息茧房。

并且由于使用 n8n + telegram channel 构建了一个输入、输出源的自动同步系统,会把我所有筛选过的信息源自动同步到我的 Telegram 频道「Yu’s Life」中,方便自己查看和回顾,顺便也作为一个个人分享渠道了,而因为有了公开的压力,也反向推动我更认真地筛选信息源。

但这个方案依然存在两个问题:

  1. 依然没能解决我信息源分散的问题,我需要频繁在 Twitter 和各个 TG Channel 之间切换,很容易分心并且依然可能会错过一些消息
  2. 我常常把频道作为我某种程度上的收藏夹,有时候很多信息很个人化,随着频道的关注者越来越多,我也会有一些心理压力,担心成为他人的信息噪音

而 follow 的出现恰好填补上了我方案的这一环。

follow

介绍

Next generation information browser

这是 follow 的 slogon,发布之前我也仅仅是把它作为一个 RSS 阅读器的 Alternative,虽然我也很熟悉 RSSHub 且自己部署了实例重度使用,但依然很难想象基于这一古早的协议还能有多大的发挥空间,直到发布和几天高强度使用后,才逐渐理解这一理念。

在 RSS 早已式微的当下,除了独立博客这一处境差不多的古早形式几乎都还保留着完整的 RSS 支持外,大部分新闻、资讯和各种小众网站都已经不再提供了,RSSHub 则是完美的且几乎是唯一的解决方案了,可以将包括但不限于 Twitter、TG Channel、Bilibili 和网易云歌单的一些网页信息源转换为标准 RSS 格式,可以像订阅文章一样获取这些信息源的更新。

然而,RSSHub 终究还是更中间层一点的工具,即使有了标准的 RSS 数据,大部分阅读器依然只能处理文本显示,对于音视频图片的处理基本上只停留在当作一个 url 这一程度,因此我更多也是应用在自己的 n8n 同步工具流中作为通知,只保留其 title 与链接,依然是点击源链接跳转会对应的网页查看,使用起来常常有些割裂。

follow 最大的特点自然还是传承于 RSSHub 的「万物皆可 RSS」理念,在应用层对视频、图片、博客音频、文章、社交媒体等多种形式的内容都提供了呈现方式,确实有一种看久了 pure html 突然飞跃到加了现代化 css 效果的感觉。其实技术层面做到这一步算不上有太高的壁垒,不论是视频 iFrame、音频播放器或是图片预览都有比较成熟的组件可以使用,但 follow 几乎是唯一一个依然在针对这一协议做且做好这一步的产品。有时候,做好一点就足够了。

体验

follow_homepage

作为一个信息浏览器/阅读器,最直观且核心的就是界面和交互了,DIYGod + 拾一两位的组合早早把我的期待值拉满,但即使是内测的第一版,其完成度和体验也依然让我感到惊艳,在此之前最现代化的应该要数 Reeder 4 了,而 follow 即使是 Electron 而不是纯原生,也依然保持了极其精致的设计和交互。

我之前用过 NetNewsWire、Reeder 4、Miniflux 和 Readwise Reader 等多款阅读器,但由于阅读体验常常还不如原网页,我大多还是会选择跳转链接查看,而 follow 的页面和交互则本身就让我享受其中,还有一个很有意思的最近阅读记录显示,可以看到自己这篇文章有哪些访客,还可以点进主页去看他们的订阅源,兼具了社交属性和信息源的积累,我就通过这种方式发现了很多之前没关注到的个人博客。

另外,由于 follow 和 RSSHub 深度集成,可以实现输入 twitter handle,B 站 uid 以及 youtube channel name 之类的来直接订阅社交媒体,而不用自己去文档找 RSSHub 网站的对应路由,也不需要自己去搭建实例,非常友好。

follow_pic

follow_video

而针对视频和图片的直接显示也是一大亮点,还看到有一个使用者将一些设计师的 Twitter 作为自己的设计灵感源和审美积累,也是很有意义的应用场景。

而音频/播客则可以在 follow 中全局播放,例如前几张截图的左下角,我就是同步在播放「代码之外」的一期节目,这也解决了我需要在 Apple Podcast、Spotify 和小宇宙等多个播客应用之间反复横跳的问题。

另外也可以比较方便地分享自己的订阅:https://web.follow.is/profile/pseudoyu

其实还有不少设计,如 Action 模块、Power 打赏等,但本文并不是一篇软件测评而是个人体验向,所以就不过多展开了,等后续开放了大家可以自己去体验一下,保留一些惊喜感。下面想谈谈和我目前所在使用的 Readwise Reader 的对比,以及我为什么打算转换到 follow。

Readwise Reader -> follow

readwise_sub

我大概是去年 9 月订阅了 Readwise Full 会员,虽然为发展中国家提供了 50% 的 discount,但依然需要接近 50 刀一年的费用,它大而全,但我使用的核心功能其实只有三点:

  1. rss 阅读器
  2. 稍后读、 保存文章与划线标注
  3. Daily Digest

其中第一点是最高频的,作为一个很方便的阅读器来管理自己的文章等订阅,也有移动端 app 可以随时看,但在使用中发现有时候显示样式和图片加载比较一般,而分类、快捷键又有点太繁复,且主要支持的还是文章,显而易见可以被 follow 完全替代(蹲一个移动端)。

划线标注之前用得比较多,会使用插件在一些文章做一些笔记,并保存到 Readwise 中,再通过 n8n 将我的文章同步到 Telegram Channel 中,但其实有些过于依赖平台了,在我真正想要消化那些划线笔记整理成一些成型的想法或是文章时则需要回到 Readwise 中去查看,即使同步到 Logseq 或是 Heptabase 中整理依然不算方便,尤其是现在转向 Apple Notes 作为自己的主力且唯一笔记工具后,发现有一些想法直接摘录/记录下来才是效率最高也更容易产生价值的,因此划词这一点渐渐淡出了我的笔记流。

save_website

众所周知,稍后读通常都会演变为稍后再也不读,所以我现在的策略是几乎不用稍后读,尽量当下就读完,只有极少数比较长的会暂存一下,也尽量在当天清空 list。我现在则是在 follow 中以未读为默认显示模式,时常会浏览一下,遇到感兴趣且通读了的文章会使用 star 功能,保存在收藏夹中,读完有所收获的时候则会通过一个自己做的浏览器插件 + Cloudflare Worker api + n8n 将文章链接及源 html 文件保存到 D1 数据库,实现 Web Archive 并自动同步到我的 Telegram Channel 中。

而第三点 Daily Digest 则是会帮助我回顾一些自己的笔记或是文章,这一点有用但并不高频,还没细研究 follow Action module 能不能针对多篇文章做一些操作。

由于我的核心需求都可以转移到 follow 中,于是果断退订了 Readwise。其实能明显地感受到这几天我的信息摄入量和质量也显著提高了,一个好的软件其实并不仅仅是辅助工具,是会对思维与习惯产生更深远的影响。

个人生活剪影

Electron Bug

talk_with_innei

刚发现 follow 客户端更新有个问题,点击「Click to restart」窗口 hide 了而不是 quit,熟悉的 bug,之前写 EpubKit 我写过一模一样的 🤣 报给了拾一,属于 electron 病情交流了。

macOS 桌面装修

macos_widgets

第一次尝试 macOS 系统的桌面小组件,还挺新鲜的,不过我基本都是 Raycast 快捷键切换应用,几乎看不到桌面…

车库墙绘

car_painting_week2

本周总体进度:20%,已经初具雏形了。

本周我的进度:画了五六块砖 🤣

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。并且把 Telegram Channel 消息作为内容源搭建了一个微博客 —— 「daily.pseudoyu.com」,可以更方便浏览了。

收藏

播客

文章

视频

电影

  • 走走停停,很喜欢最后高速堵车那段的镜头语言,人生不过走走停停。

周报 #66 - 10x 工程师、技术热情与个人工具箱

《Photograph - Ed Sheeran》

前言

weekly_review_20240730

本篇是对 2024-07-222024-07-30 这周生活的记录与思考。

经过了异常丰富的 Adventure X 一周活动,算是回归了沉下心写代码的日常。忙于一些工作需求;使用 Cloudflare Worker 继续开发 EpubKit 的 api 部分功能;使用 Go 重构了一年多前就启动但是一直没成型的 side project 后端部分,并开始尝试用 rust 写一个 api server;为自己一个个人工具箱项目「GitHub - yu-tools」写了一个 Astro 网页项目「tools.pseudoyu.com」;写了 Remark42 部署的教程博客,并经过了一位在搭建博客系统的读者的可行性验证;全家去千岛湖一个水上乐园玩,感觉自己太现充了;尝试水彩画,并启动了车库墙绘项目;还有很多有意思的事。

10x 工程师

randy_10x

Randy 最近上线了一个「Ask Hackers」项目,是一个基于 Hacker News Comments 的搜索工具,感觉从想法萌生到上线推广大概也就一两天,想到了一个叫「10x 工程师」的概念,能够快速将自己的一个想法开发实现,很羡慕。

自己其实前前后后也做了不少工作和个人项目,惭愧地说技术栈接触了不少,都能写一点但也都不深,快速实现和迭代一个产品的能力还是很差,似乎从想法到 Demo/产品之间依然差了一环,也跟 Randy 聊过这个话题,他觉得还是工程经验的问题,他看到某个网站或者 App 的某个效果,基本上能大致猜到实现的方式并复现,而我可能还是得靠去看源码或者咨询 AI 才能勉强做到。

技术热情

除此之外,我发现热情和动力也左右着我的行为,可能是由于依然没有找到自己的产品 Idea 和方向,总是感觉自己之前做 side projects 的时候仅仅是在“实现”或是技术练习,吸引我的并不是产品成型本身而是在实现过程中的了解学习和技术能力的提升,对于个人来说无可厚非,但对于一个产品来说似乎是缺少了灵魂,就像第一次见 Randy 时我好奇地问他为什么不再更新 Cusdis 了,有不少 Star,也有包括我在内的很多自部署用户,印象里他说除了经济因素外,更多是由于自己没有动力去做了,没办法为一个自己都不会去用/为之付费的产品付出更多的热情。

其实自己的症结也在于此,似乎依然没有找到会让自己半夜兴奋到睡不着的想法,反倒是在一起开发 EpubKit 时,由于自己也是电子书的多年用户,从自己作为用户的角度出发,能够对产品的迭代有更多想法和热情,也会更有成就感。

自己一定要是产品的第一个用户。

个人工具箱项目

yu_tools_website

自己一直是一个各种软硬件的重度折腾爱好者,几乎每一个自己很小众的需求都会花大量的时间挑选出最合适的工具,哪怕检索的时间远远超过了使用工具本身,依然乐在其中。从大学到现在,身边也有无数人会问我类似“有什么推荐的相机/键盘/麦克风/xxx 么”、“我想在手机上做 xxx 有什么推荐的软件么”这类的问题,于是两年多前萌生了自己做一个个人工具箱列表的想法 —— 「GitHub - yu-tools」。

最开始只是一个简单的 GitHub 项目和一个 README.md 文件,后来慢慢添加了一些分类,并为每个条目增加了一条简短的描述,两年里阶段性更新了几次,没想到竟成为了我 star 最多的一个 repo 了。

之前有看到过自己很喜欢的开发者「devaslife/Takuya Matsuyama」做的一个工具箱网站 —— 「A curated list of the tech I use」,为每一个工具拍照并附上使用体验,觉得很有价值,于是也花了一晚上参照他的模板使用 Astro 做了一个网站 —— 「tools.pseudoyu.com」,只是会更多地偏向软件和服务,而随着条目增加,也想添加类似「Ask Hackers」的对话搜索功能。

软硬件的拍摄、截图和介绍是个大工程,持续更新中,有需要的朋友可以关注一下。

个人生活剪影

水彩

rust_painting

某次饭后家人一起尝试在扇子上画水彩,也是全新的体验,挑选了 Rust 小螃蟹,在学姐的亿点指导下完成了这幅作品,很开心!!!

车库墙绘

wall_painting

既上次使用 DALL-E 生成了想要在车间墙绘的图之后,这种终于得空开工,进度 30%,但是由于周一晚刚好组会,是学姐和我妹妹画的,带了相机也没来得及用相机记录下完整过程,有些遗憾,下次会多拍一些流程和细节,期待最终效果。

捏捏

nienie_on_desktop

最近或许是察觉了我的忙碌,两只小猫都变得更加黏人,每次写代码时捏捏也都静静趴在桌上,时不时伸个懒腰或者发个嗲,松弛而治愈。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。

收藏

书籍

  • Shape Up,可汗学院创始人写的关于 GPT 与教育未来的思考与实践,对日常使用 LLMs 有挺多启发的,除了成为搜索引擎一样的工具向外还有很多想象空间。

文章

视频

剧集

从零开始搭建你的免费博客评论系统(Remark42 + fly.io)

前言

在「2024 年了,我的博客有了什么变化」一文中,我介绍了自己使用 Serverless 平台和一些开源项目搭建的博客系统,也开启了这个系列教程来记录搭建和部署全过程。

本篇是关于评论系统的解决方案。

评论系统迭代

remark42_comments

我常常觉得评论不仅仅是读者与作者之间的沟通互动,其内容本身也是文章的一部分,甚至常常有些评论的思考与观点讨论会比文章本身更有价值,所以对于评论系统一直很重视,并不愿意信任一些第三方托管的服务,不希望有什么审查,也想风格尽可能简约,并与自己的博客风格相符。

在博客发展过程中,评论系统方案也经历过几次迭代,关于评论系统的类型和选择,我很喜欢的开发者 reorx 在「更换博客评论系统」中有详细的介绍了,我不作更多引申了,本文更重个人体验与详细的搭建过程。

Disqus

我最早使用的博客评论系统是万恶的 Disqus,一个笨重且会收集用户隐私的知名评论系统,因为加载比较慢,且免费版本经常会附带一些广告,实在难以忍受,再加上当时其实也基本上没什么评论,并没有什么迁移负担,用了没多久就直接弃用了。

Utterances

于是换成了另一个基于 GitHub issues 的评论系统 utterances,它会为每篇文章生成一个 issue,用户通过授权 GitHub 登录来对 issue 发表评论。这种方式的好处是只需要授权一个 utterances-bot 来进行管理,无需自己部署服务,维护数据库等。但是用了一段时间后,觉得有几点不足:

  • 基于 GitHub API 进行评论管理,如之后接口变动或对这类利用 issue 进行评论的方式进行限制,会不太稳定
  • 读者必须要授权 GitHub 登录,非技术人员或使用移动端阅读的读者使用起来很不方便
  • 会污染 GitHub 仓库的 Issues 记录,也不方便后续迁移到其他系统

Cusdis + Supabase + Vercel

Cusdis 是 Randy 做的一个注重数据隐私的开源的评论系统,十分轻量,经过 gzipped 后大约只有 5kb,从名字来看也知道是难以忍受 Disqus,自己做了一个替代版,因此它也是支持 Disqus 历史数据导入的,很贴心。

从 2021 年中就开始使用了,到现在整整三年了,除了最开始的时候因为 Heroku、Railway 相继收费而折腾了一下部署平台外,一直都稳稳地运行着,不过我在使用中也有遇到一些问题:

  • 大概是由于微信内置浏览器做了一些魔改,在博客从微信聊天/对话打开是看不到评论组件的
  • 尽管可以输入邮箱,但并不支持订阅评论回复
  • 需要管理员手动审核评论,但评论提醒的 TG Bot 时常失效而错过评论

不过整体来说时至今日依然是十分值得推荐的方案,轻量,方便自部署,风格也简约好看,搭建教程参看「轻量级开源免费博客评论系统解决方案 (Cusdis + Railway)」。

鉴于 Railway 从去年 8 月起已经取消了 Free Plan,如果依然想完全免费使用,可以使用 Vercel/Netlify/Zeabur 免费部署主项目,并在 Supabase 上部署一个免费的 PostgreSQL 数据库实例,把链接作为环境变量传入 Cusdis 服务中即可,其他流程大同小异。

另外因为其核心功能已经许久没有什么更新,比起其他较为成熟的评论系统也显得有些简陋,不过由于我也秉持着够用即可的原则,一直没动迁移/更新的念头,只有在其中一阵子在学前端时还参与了一些 Cusdis V2 版本的开发,不过也没做多久。

由于四月时 Vercel 部署升级的时候一直失败,导致接近几周的时间没收到评论,再加上确实有了一些功能需求,所以下定决心进行迁移,探究起了新的方案。

Remark42 + fly.io

调研了一圈后选择了 reorx 在「更换博客评论系统」一文中最后选定的 Remark42

单纯就配置选项来说比起 Cusdis 还是丰富了不少,目前配置了常用的几种社交账号登录(GitHub、Twitter、Telegram、邮箱)、可以匿名评论、支持邮件订阅回复提醒并且也设置了 TG bot 提醒,并且部署在 fly.io,go 单二进制 + 数据库单文件,很舒服的解决方案,更详细的 Remark42 的介绍和优势可以参看上面那篇文章。

虽然 Remark42 提供了一些迁移方案,但本身并不支持我使用的 Cusdis,但好在它是用 Golang 写的,我自己添加了迁移逻辑,将这些年沉淀下来的 438 条评论数据都无缝迁移过来了。

Remark42 + fly.io 部署说明

Remark42 + fly.io 的方案仅牵扯到单个服务,数据库使用的是 boltdb 挂载于 volume 中,但所有操作都在 fly.io 的 Free Plan 中。

下面将从零开始介绍如何搭建这个免费评论系统。

Remark42 本身代码开源 —— 「GitHub - umputun/remark42」,并提供了官方维护的镜像,文档清晰易读,可以根据自己的实际需求进行配置。

安装 flyctl 命令行工具

fly.io 与我之前使用的 Railway、Zeabur 等很大的一个不同点是它大部分操作基于命令行与配置文件,而不是在网页端管理后台进行操作,所以首先需要根据文档安装 flyctl 命令行工具。

以 macOS 为例,我使用 brew 进行安装:

brew install flyctl

授权登录

打开终端工具,使用以下命令进行授权登录:

flyctl auth login

fly_auth_login

fly_auth_web

在 Web 端进行账户登录或新建账号,完成后点击 Continue as xxx 即完成 flyctl 命令行的授权登录。

创建应用目录

create_fly_config

由于我通常会手动进行进行配置管理,而不是用它官方的模板,所以我会新建一个类似 remark42-on-fly 的目录,并将所有的配置文件、环境变量等放在这个路径下。

并使用 VS Code 进行编辑(也可以使用 vim 或者其他编辑器/IDE)。

配置文件

fly.io 主要是使用 .toml 格式的配置文件进行服务管理,以下是我部署的服务对应的配置文件:

app = 'yu-remark42-01'
primary_region = 'hkg'

[build]
  image = 'umputun/remark42:latest'

[[mounts]]
  source = 'remark42_data_01'
  destination = '/srv/var'

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = false
  auto_start_machines = true
  min_machines_running = 1
  processes = ['app']

[env]
  REMARK_URL = 'https://yu-remark42-01.fly.dev/'
  SECRET = 'remark42-secret'
  SITE= 'remark42-demo'
  ADMIN_SHARED_ID= ''

[[vm]]
  cpu_kind = 'shared'
  cpus = 1
  memory_mb = 256

这是详细的配置说明:

  • app:应用名称,这里我使用了 yu-remark42-01,可以根据自己的实际情况进行修改
  • primary_region:部署区域,可以从这个列表中选择自己想部署的区域,我选择了香港
  • [Build],这个部分主要是服务镜像相关的配置
    • image:服务镜像,使用了官方提供的 umputun/remark42:latest,如有需要可以指定 tag 版本
  • [[mounts]],这个部分主要是挂载数据卷的配置,由于 Remark42 使用 boltdb 数据库,需要持久化存储
    • source:数据卷名称,这里我使用了 remark42_data_01
    • destination:挂载目录,这里我挂载到了 /srv/var,这个目录是 Remark42 默认的数据存储目录
  • [http_service],这个部分主要是服务相关的配置
    • internal_port:服务内部端口,使用 8080
    • force_https:强制使用 HTTPS
    • auto_stop_machines:设置为 false
    • auto_start_machines:设置为 true,即自动启动
    • min_machines_running:最小运行机器数,设置为 1
    • processes:服务进程,设置为 app
  • [env],配置环境变量
    • REMARK_URL:Remark42 服务的 URL,这里我使用了 https://yu-remark42-demo.fly.dev/,这是 fly.io 自动生成的,后续如果有了自定义域名则需要更改
    • SITE:站点名称,这里我使用了 remark42-demo
    • SECRET:自定义的 JWT Token,这里我使用了 remark42-secret
    • ADMIN_SHARED_ID:管理员 ID,这里我使用了空字符串,即没有管理员,后续可以补充
  • [[vm]],这个部分主要是机器相关的配置
    • cpu_kind:CPU 类型,设置为 shared
    • cpus:CPU 数量,设置为 1
    • memory_mb:内存,设置为 256MB

创建服务

完成并检查配置后,运行以下命令进行服务创建:

flyctl launch

fly_launch_remark42

环境变量配置

目前只是部署了服务,并没有设置环境变量,因此服务启动会有问题,接下来我们设置环境变量,放在prod.env 文件中:

AUTH_GITHUB_CID=<your_github_cid>
AUTH_GITHUB_CSEC=<your_github_csec>
AUTH_TWITTER_CID=<your_twitter_cid>
AUTH_TWITTER_CSEC=<your_twitter_csec>
AUTH_ANON=true
AUTH_TELEGRAM=true
TELEGRAM_TOKEN=<your_telegram_token>
NOTIFY_ADMINS=telegram
NOTIFY_TELEGRAM_CHAN=<your_telegram_group>
NOTIFY_USERS=email
AUTH_EMAIL_ENABLE=true
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_TLS=true
SMTP_USERNAME=xxx@gmail.com
SMTP_PASSWORD=<your_password>
AUTH_EMAIL_FROM=xxx@gmail.com
NOTIFY_EMAIL_FROM=xxx@gmail.com

环境变量的部分相对比较复杂,具体参数参看文档

登录/授权配置

我配置了匿名评论、GitHub、Twitter 与 Telegram 几种方式,可以根据自己的情况配置其他登录方式。

  • 匿名登录
    • AUTH_ANON:是否允许匿名评论,我选择了允许,即用户可以不登录评论
  • GitHub 登录
    • AUTH_GITHUB_CIDAUTH_GITHUB_CSEC:GitHub OAuth App 的 Client ID 与 Client Secret
  • Twitter 登录
    • AUTH_TWITTER_CIDAUTH_TWITTER_CSEC:Twitter OAuth App 的 Client ID 与 Client Secret
  • Telegram 登录
    • AUTH_TELEGRAM:是否允许 Telegram 登录
    • TELEGRAM_TOKEN:Telegram Bot Token,通过 botfather 创建
  • 邮箱登录
    • AUTH_EMAIL_ENABLE:是否允许邮箱登录
    • AUTH_EMAIL_FROM:邮箱登录的发送邮箱

通知配置

  • Telegram 通知管理员,参看文档这部分进行 Telegram Bot 的创建和配置
    • NOTIFY_ADMINS:通知管理员的方式,选择 telegram
    • NOTIFY_TELEGRAM_CHAN:如启用 telegram 通知管理员,需要配置对应 Channel id,只需要填写 t.me/xxx 后面的 id 部分即可,如 pseudoyuchat
  • Email 通知用户,参看文档这部分进行邮箱 SMTP 等配置
    • NOTIFY_USERS:通知用户的方式,我选择了了 email, 即邮件通知,则需要配置下文的 SMTP
    • NOTIFY_EMAIL_FROM:邮箱通知的发送地址

邮件 SMTP 配置

上文的邮箱登录与邮箱通知都需要配置 SMTP 服务器,这部分也可以根据自己的邮箱服务商参照文档进行配置。

  • SMTP_HOST:SMTP 服务器地址
  • SMTP_PORT:SMTP 服务器端口
  • SMTP_TLS:是否启用 TLS
  • SMTP_USERNAME:SMTP 用户名
  • SMTP_PASSWORD:SMTP 密码

导入环境变量到服务

根据以上说明完成环境变量配置后,在配置文件和环境变量文件所在目录运行以下命令导入环境变量:

fly secrets import < prod.env

fly_secret_import

deploy_status_remark42

执行完成后到 fly.io 控制台查看服务状态即可,如为 Deployed 状态即表示部署成功。

配置自定义域名(可选)

如果你不想使用 fly.io 提供的默认域名,可以配置自定义域名。

custom_domain_flyio

进入 fly.io 控制台,选择刚部署的 yu-remark42-01 服务,点击左侧的 Certificates 选项,然后点击右上角 Add a Certificate,按照提示添加自定义域名即可。

custom_domain_dns_in_fly

点击 Create Certificate 后,会有一个页面显示你所需要添加的 DNS 记录,按照提示添加即可。

cloudflare_dns_remark42

flyio_certificate_success

例如我的域名托管在 Cloudflare,我按照提示添加了两条 DNS 记录,返回页面后点击 Check again 或等待一段时间后刷新查看,都显示绿色即为配置成功。

change_remark_url

此时,我们可以在 fly.toml 中修改 REMARK_URL 为自定义域名,然后执行以下命令重新部署服务即可,之后对配置文件进行任何改动都可以使用该命令进行更新:

fly deploy

博客配置 Remark42

上文我们完成的 Remark42 服务的部署,现在则需要在我们的博文中加入 Remark42 评论组件,以我使用的 Hugo 博客为例。

定义 Hugo 主题 Comments 组件

我在 Hugo 博客的 layouts/partials 目录下新建了一个 comments.html 文件,用于定义 Remark42 评论组件:

<div class="comments">
  <div class="title">
    <span>Comments</span>
    <span class="counter"><span class="remark42__counter" data-url="{{ .Permalink }}"></span></span>
  </div>
  <div id="remark42">
  </div>
</div>

<script>
  var remark_config = {
    host: 'https://comments.pseudoyu.com',
    site_id: 'pseudoyu.com',
    components: ['embed', 'counter'],
    max_shown_comments: 20,
    simple_view: true,
    theme: 'light',
  }
</script>

<script>
    (function () {
      // init or reset remark42
      const remark42 = window.REMARK42
      if (remark42) {
        remark42.destroy()
        remark42.createInstance(remark_config)
      } else {
        for (const component of remark_config.components) {
          var d = document, s = d.createElement('script');
          s.src = `${remark_config.host}/web/${component}.mjs`;
          s.type = 'module';
          s.defer = true;
          // prevent the <script> from loading mutiple times by InstantClick
          s.setAttribute('data-no-instant', '')
          d.head.appendChild(s);
        }
      }
    })();
</script>

remark_config 中的 hostsite_id 需要根据自己的实际配置进行修改,其他部分配置可以保持不变,或根据文档进行调整。

配置好 commnets 组件后,在 layouts/posts/single.html 中文章底部引入:

{{ partial "comments.html" . }}

add_comments_code_in_hugo

大体位置如图所示,如使用的是其他主题或博客系统,则需要找到自己文章对应的模板文件进行修改。

本地预览/部署网站

test_remark42_embedded

此时可以在本地预览或部署网站以查看评论系统是否正常显示,至此我们的服务部署完成。

获取 User ID 并配置 Admin

get_user_id_remark42

登录授权完成后并测试评论后,可在 Remark42 中点击头像打开管理页面,双击后 CMD/Ctrl+C 可以获取以 github_ 或其他平台开头的 User ID,可以将其配置到 ADMIN_SHARED_ID 中(更改 fly.toml 配置文件并运行 fly deploy 重新部署,即可成为管理员,管理员有权限对其他用户的评论进行删除等管理操作。

其他

我把之前 Cusdis 中的评论数据按照一定条件导出 json 格式的数据,并通过 go 程序进行格式转换与迁移,因此保留了之前所有的评论。

因为 Cusdis 本身不提供导出功能且迁移的需求太过小众,我并没有直接向上游贡献代码,也没有写成完善的脚本,有类似需求的朋友可以参考这个 PR 进行处理 —— 「feat: add cusdis to remark42 migrator support by pseudoyu · Pull Request #1 · pseudoyu/remark42」。

总结

以上就是我的博客评论系统的搭建过程,评论系统的搭建与配置相对繁复,且本文的配置方式或许会随时时间而过时,遇到问题可多参照官方文档

这是我的博客搭建部署系列教程之一,如对数据统计系统、博客内搜索等搭建感兴趣,请持续关注,希望能对大家有所参考。

周报 #65 - Adventure X 体验、Apple Notes 笔记实践与 EpubKit

《Photograph - Ed Sheeran》

前言

weekly_review_20240721

本篇是对 2024-07-102024-07-21 这周生活的记录与思考。

这一周多很丰富,工作有些忙碌,参加 Adventure X 的活动,很好玩;尝试了 Remix 框架,筹备一个 Workshop;和 Randy 见面,一起计划了 EpubKit 的 Redesign 和后续开发安排,算是给我们无法参赛的“中年嬉皮士”举办了自己的黑客松;从 Obsidian 转向 Apple Notes,实践 P.A.R.A;打算给车库的墙进行喷绘;去 Apple Store 体验了 Apple Vision Pro;还有很多有意思的事。

Adventure X

这是一个面向 26 岁及以下的年轻开发者的一个黑客松活动,早早有听到宣发,刚好超龄而遗憾没法报名参加,不过受邀作为 OpenBuild 赞助的「互联网 3.0 开发工具」赛道的评委及 Workshop 的讲师来到现场,也算是全程观望了。

活动大概有接近两百个开发者参赛,确实能看到他们的活力和激情(可能限制 26 岁也是有道理的);以及有不少在 Twitter 和疯狂星期四上熟识的朋友们都来到了现场,跟其中不少新老朋友聊了一些有意思的事。

Workshop

adventurex_workshop

这次主要的任务是作为 Mentor 和 Workshop 的讲师,主题为「使用 Solidity 与 Remix 构建全栈 AdventureX Badge ÐApp」。

其实前前后后在不少场合讲了不少次课和 Workshop,一开始其实只是给 ian 的 OpenBuild 社区帮忙,自己也是乐于写教程和分享的,但随着这样的机会越来越多,自己也有了一些变化,并不会每次都用一样的课件重复着类似的内容,而是都当作一个自己学习的新机会,也让自己在有限的时间内完成一些好玩的东西,再把它教授出去,也是费曼学习法的一种实践。

这次 Workshop 则是想要学习 Remix 前端框架,写了一个简单的活动徽章领取的 ÐApp,体验地址是 —— 「adventure-x.pseudoyu.com」,PPT 课件是 —— 「AdventureX_Workshop_20240716.pdf」。

虽然大概一个月前就知道这个 Workshop,但毫无意外地拖到了前两天,花了一晚上学习了 Randy 的「Remix 入门实战」小册子,写完了 UI 部分,然后又花了一晚上写 Solidity 合约部分,并且完成了前端和合约的交互逻辑,并且用 Zeabur 部署上线了,拖延症真的要命。

但是 Remix 确实好用,实现 0 useEffect, 0 useState 写完应用成就,后面看看能不能在各种场景上都彻底替代 Next.js。

现场来的人比想象得多,比起原定的 45 分钟也拖堂了一倍,接近 10 点才结束,不过是很有意思的体验,Workshop 效果也不错。

“中年嬉皮士”黑客松

code_with_randy_hackathon

这次 Randy 也作为嘉宾评委从广东过来了,都觉得黑客松氛围都到这了,我们只是观光有些太无趣了,所以干脆一起做起了 EpubKit 的 Redesign。

讨论了整个 EpubKit 现有的操作逻辑和 UI 风格变动,很开心,晚上一起开发了几个小时,也是找找作为“中年嬉皮士”的参与感了;也讨论了后续关于产品的很多想法和分工,很期待。

也欢迎大家下载体验 EpubKit,制作自己的电子书。

yu_with_randy

作为不爱拍照的人,刚好被工作人员拍到了和 Randy 一起在看项目展览时候的合影,也很有纪念意义了。

基于 Apple Notes 的 P.A.R.A 实践

上个月从用了两年的 Logseq 转成了 Obsidian,实践了大概一个月,比起 Logseq 的时候多了好些记录的习惯,虽然已经不用再关心文件夹层级这些,但依然需要克服,「脑子里记录下想法」 -> 「等在电脑前新建文件并取标题」 -> 「整理想法并打 Tag」 -> 「写下内容」这一链路所带来的心智负担。

apple_notes_folders_20240721

Randy 跟我讲了他使用 Apple Notes 记录所有想法和笔记的方式,并通过 P.A.R.A 的层级进行分类,发现当不需要有整理的负担,而是随时打开手机/电脑记录下想法,也不用考虑什么格式或是 markdown 语法,会更有记录的欲望,而能记下来、take action 才是笔记的核心要义。

在 Mac 上可以使用右下角的 Quick Notes 快速记录,iOS 上则是通过快捷指令将一些闪现想法快速保存到 Drafts 目录中,后续有更多想法的时候再挪动到各个目录中,很简单却有效的实践,也不需要再指定各种 tag 和分类,需要的时候直接全文搜索就可以了。

其他

墙绘

car_painting_wall

上次学了油画画了头像后觉得很有意思,最近打算再挑战一下好玩的,和学姐一起给我爸的汽修车间的一整面水泥墙用丙烯颜料墙绘(我打打下手)。

把我爸的想法和我们在 Ins 上找的参考图发给 DALL-E 后生成的效果很不错,希望 8 月能有成品效果 🤩。

Apple Vision Pro

apple_vision_pro_experience

这周四去 Apple 西湖体验了 Vision Pro,其实之前非常早就关注了,也看了大量测评,一度有些心动,但是其实有过 Quest2 的吃灰经历,一直还在观望。

刚好国行也上架了,预约了一次半小时的体验,从配镜片、讲解配件到体验各种功能和应用,体验的感觉比想象得好,20 分钟左右的时间倒也没有感受到什么眩晕感或是重量带来的压力。

实际体验下来,交互比想象得流畅自然和准确;但画面还是有比较明显的噪点,分辨率并不足以有沉浸式的体验,但已经是比较惊艳的了;应用支持还是太少了,所以更多也就是尝鲜,没有什么应用场景,打字体验很差,还是得外接键盘;总体来说,这一代不太值得买,或许等待之后不论价格还是系统应用层完善了再考虑了。

ChatGPT Plus -> Claude Pro

claude_pro_sub

上个月由于用得比较高频,重新订阅了 ChatGPT Plus,同时用着免费额度下的 Claude 3.5 Sonnet,发现在代码上 Claude 的上下文理解能力和生成结果的可用性都明显强于 GPT4,于是在这周到期的时候决定改为 Claude Pro 的订阅,在价格相同的前提下再体验一个月试试。

Guii 体验

guii

Guii 是这次 Adventure X 黑客松看到的最有意思的项目了,能够直接通过自然语言对话的方式跟前端页面交互,并直接会更改源码实现有趣的效果。

我通过选中元素简单对话的方式做了一个很简易的数字货币小网站,还有些 bug 但是可玩性很高。

把 OpenBuild Sponsor 赛道的奖项颁给她们了,实至名归,希望能早点上线 🔥。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。

收藏

书籍

  • Brave New Words,可汗学院创始人写的关于 GPT 与教育未来的思考与实践,对日常使用 LLMs 有挺多启发的,除了成为搜索引擎一样的工具向外还有很多想象空间。
  • 履单,从萝卜快跑引起的议论想到的这本书,探讨科技加速引起的社会分化,不过更多是从劳动者视角,下午看了一会儿,叙事方式也很舒服。

文章

视频

音乐

周报 #64 - 生活在此处(《斯通纳》与《Normal People》)

《Photograph - Ed Sheeran》

前言

weekly_review_20240710

本篇是对 2024-07-012024-07-09 这周生活的记录与思考。

这一周坚持了几天早起读书学习,效率很高,不过要养成规律依然需要时间调整,也还在探究如何更快地进入/切换工作状态;在同步看几本书,《阿特拉斯耸耸肩》、《Normal People》与《What My Bones Know》,和学姐聊到她正在看的斯通纳,有了一些关于人生各个维度的思考;还有很多有意思的事。

Normal People 与斯通纳

normal_people

《Normal People》是一部好久之前的英剧了,大概是 20 年还是 21 年的时候看的,印象很深,最近突然想起就看了下原著,虽说内容大多关于爱情与学校的琐事,我却能够在男主身上看到许多自己,根植于内心深处的怯懦与不安,对于生活迷茫却又不甘平凡的执念,以及最终又承认生活本就如此的释然;《斯通纳》则是前段时间抽奖的书籍盲盒中我挑选的其中一本,之前已经看了两遍,剧情已经记不太清,却有一种回想起来常看常新的感觉,用平淡的笔触勾勒生活原本的样子。

这两本书连在一起,让我重新思考了一些关于自我与人生的价值命题。

生活在此处

昨晚和学姐久违地找了周遭一家日料店出门约会,我们各自从家出发,对方的打扮都很搞笑,她上身穿着华丽的连衣裙,却踏着一双拖鞋;我也没好到哪去,上身衬衫,下身运动短裤加拖鞋。坐在吧台等餐聊天时,有一种一半仪式感一半生活的混搭感,却又不显得怪异,就像个生活搭子。

我们常常说“生活在别处”,意为别处的生活似乎总是吸引着我们,但其实回望看看,此处的生活其实也别具魅力。

我们聊到现在的生活,感觉似乎并没有什么太值得埋怨的,她在不算喜欢也不算讨厌的工作中能做得很好,我在自己的领域中自得其乐;在杭州的生活节奏好过北京的纷扰,时常能漫步或是回家吃上一顿家常。但我们似乎都有所期待,她想去画画,我也想离开这个舒适圈去另一个国度开启新的生活篇章,只是这种期待被还不错的生活现状所掩盖,反倒有些难以抽身了,毕竟没有现实需求驱动的决定总是会更难一些的,似乎自己总要背负着打破生活平静的责任。

虚无的意义

读书和刚毕业那一两年常有很多学弟学妹来问我关于转码、人生选择的一些建议,乃至现在也有一些从技术教程或是课程了解到我的朋友来问我关于 Web3 学习和行业的一些问题,我一直都很谨慎而认真地对待他们,因为常常想到当年我如果能早些得到一些建议,或许就能够少走一些弯路,但有警惕自己的语气与姿态,不愿因幸存者偏差而变得“好为人师”。

于是常常条分缕析地根据他们每个人的情况列出一些利弊和我自己的想法,连续七八条消息过去,还生怕有些什么遗漏,可十之八九,最终他们都会以这么几句来追问,仿佛我说的那些都无关紧要,也并不是他们想要的答案,颇有些图穷匕见的荒谬感:

“计算机是不是很赚钱啊,我怎么样才能转码成功啊?”

“Web3 工资是不是很高啊?”

之前很喜欢一句话,来自很久之前某个很欣赏但却早已停更的文字博主每篇文章结尾,大意是:

「我把我知道的道理全都告诉你,为的是让你过不好这一生」。

有时我常常在想,是不是正是因为我过于追求虚无的意义,徒有一些原则,反而让自己不那么开心了,人总是知道的愈多愈加难以前行,人生不过三万天,或许甘于外物,甘于生活本身,人生会“松弛”许多。

于是也有过很长一段时间的沉默,不再向自我和这个世界提问,享受当下,收获的却是更多虚无。

其他

工作状态

最近工作在做一个有点麻烦的需求,大概有一周了,其实技术上倒也没什么特别的难点,无非就是从链上读取配置,并且调度各个服务重启(但是不能从 k8s 或者其他部署层面,而是需要程序内部自己处理),因而链路有很多细节要考虑,需要很专注和细致。

而这周又实践了一段时间的 5 点起床沉浸式写博客、阅读、学习 Rust 等,到 9 点多开始逐渐调整到工作状态,一直到晚上。因为早起的效率还挺高的,反而发现从学习状态切换到完全的专注工作状态其实很难/很慢,也就是之前代码之外一周年直播里面 Randy 提到的“单线程”和“上下文切换”,没有办法同时深度思考和做两件事。

又想到上周跟同事 Ares 去良渚咖啡厅里办公,虽然工作过程中只是闲谈几句,跟正在做的工作内容也不强相关,但似乎一下子就会拉入了良好的工作的氛围中,而自己在家有时候就并不那么容易做到这样,这大概也是远程办公的一种弊端吧。

生活日常

mats_cat

最近家门口地垫是这个(当代年轻人精神状况 🤣

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。

收藏

书籍

  • Normal People,很喜欢这个英剧,这两天看其他书的时候突然想到了这本,打算补一下原著。
  • What My Bones Know,去年看了一小半,这两天想到关于家庭和心理疗愈的问题,每天看一章左右。
  • 阿特拉斯耸耸肩,读者送的,读了前两张章了。

文章

播客

电影

  • 泳者之心,感觉对于片名「Young Woman and the Sea」中文翻译「泳者之心」有些过于平淡,看完后可能觉得「老娘与海」比较适合 🤣 体育精神、女性、励志,主题上算不上有多新颖,但对于女主的成长和她身边的支撑刻画得恰到好处,女主的妈妈和教练艾比也让人印象深刻。学姐之前曾报名横渡香港维港,现在也在备战横渡杭州钱塘江,难度与英吉利海峡自然不可比,但看完后似乎更能理解了这其中的执念与魅力。

视频

使用 WebP Cloud 与 Cloudflare WAF 为你的图床添加隐私和版权保护

前言

在「从零开始搭建你的免费图床系统 (Cloudflare R2 + WebP Cloud + PicGo)」一文中,我用 Cloudflare R2 搭建了一个免费的图床系统,并通过 WebP Cloud 进行图片优化。

在使用 WebP Cloud 的过程中,我发现它还提供了自定义 Proxy User Agent、水印等功能,于是萌生了一个想法,是不是可以通过 WebP Cloud 对我的图床源站链接进行保护,使 WebP Cloud 的代理链接成为访问我所有图片的唯一入口,并统一添加我的专属版权水印。

本文是对这一实践的记录,也算是图床搭建番外篇了。

需求分析

webp_proxy_info

我目前的图床方案是将图片都托管在 Cloudflare R2 上,并且通过 WebP Cloud 这一强大的图片代理工具进行访问优化,但其实使用代理链接 image.pseudoyu.com 与源站链接 images.pseudoyu.com 都可以访问我的图片,只是前者被优化过,后者则是我保存的原图。

隐私保护

事实上我们通过手机、数码相机等设备拍摄的照片都会携带 EXIF(EXchangeable Image File Format) 信息,通常会包含拍摄设备、时间和地点等敏感信息,我们可以通过一些技术方式手动去除这些元数据,但操作十分繁琐且容易遗漏。

webp_exif_remove

我查阅了一下 WebP Cloud 的文档,发现它果然提供自动擦除 EXIF 信息的功能,无须额外配置操作,但其实访客依然可以可以通过 Cloudflare R2 暴露出的源站信息访问到原图,为了避免这一点,我需要限制用户只能通过 WebP Cloud 代理链接进行请求,访问 Cloudflare R2 源站链接时获取不到任何有用信息。

版权保护

randy_pic_copyright

之前在推上看到 Randy 自己拍的 desk setup 图被盗用的经历。

而自己也玩一些摄影,虽没什么特别的商业价值,但终究是自己的作品,理应保护版权,因此我想在图片上统一添加自己的版权水印,以防止被他人盗用。

实现方案

需求清晰了,其实主要分为两部分:

  1. 让用户只能通过 WebP Cloud 代理链接访问到我的图片,禁止直接访问原图链接
  2. 在 WebP Cloud 代理层面为所有的图片统一自动添加自己的版权水印,无须手动操作

以下是我的实现方案与详细步骤。

WebP 自定义 User Agent + Cloudflare WAF

WebP Cloud 的开发者 Nova Kwok 聊了一下,发现 WebP Cloud 提供了自定义「Proxy User Agent」的功能,并推荐在 Cloudflare WAF 中配置对应规则以保护图片安全,文档中有详细说明 – 「Security | WebP Cloud Services Docs」。

WebP Cloud 配置

当我们访问互联网上的网页或图片链接时,请求通常会包含一个 User Agent 字段,一般包含浏览器版本等信息,网站可针对不同的 User Agent 进行一些特定逻辑处理。

WebP Cloud 默认会使用 WebP Cloud Services/1.0 作为值,也就是不论用户访问图片时使用的是什么终端设备和浏览器,请求到 Cloudflare R2 时都会被统一为 WebP Cloud 定义的 User Agent 值,而这个值又是用户可以自定义的。

webp_custom_user_agent

因此,我们登录 WebP Cloud 的控制台,将「Proxy User Agent」字段设置为一个自定义值,如 pseudoyu.com/1.0

Cloudflare WAF 配置

cloudflare_waf_intro

WAF(Web Application Firewall) 是 Cloudflare 提供的一个防火墙服务,可以自定义规则来限制特定请求以保护网站安全,登录 Cloudflare 后在左侧边栏点击「网站」,点击进入需要保护的域名,选择侧边栏「安全性」 - 「WAF」即可免费使用(注:不是最外层的账户级 WAF),免费账户可设定五个自定义规则。

waf_create_rule

点击「创建规则」,进入设置页面。

user_agent_protection_waf

点击「表达式预览」右侧的「编辑表达式」,填入以下规则:

(http.user_agent ne "pseudoyu.com/1.0") and (http.host eq "images.pseudoyu.com")

首先,需要把其中 pseudoyu.com/1.0 这部分填入上文在 WebP Cloud 中你自定义的 User Agent 值;另外,为了防止我在同一域名下的其他自部署服务的图片无法正常显示,我添加了 (http.host eq "images.pseudoyu.com") 条件,即只对图床的访问链接生效,这部分需要替换为自己的图床域名 host。

并且在「选择操作」下拉选择「阻止」,这样会匹配我们的规则并阻止特定网络请求,编辑完成后点击「部署/保存」即可。

我使用的是目前 WebP Cloud 官方文档提供的推荐规则,后续或许会针对新的功能有所调整,可以直接参考文档。

block_by_waf_example

完成配置后,当我们再次访问以 images.pseudoyu.com 开头的源站链接时会被 WAF 拦截,例如:

images.pseudoyu.com/images/new_mbp_setup.jpg

而经 WebP Cloud 代理过的链接则可以正常访问,例如:

image.pseudoyu.com/images/new_mbp_setup.jpg

完美实现了我们的需求。

使用 WebP Cloud 为图片添加版权水印

经过了上文的操作,我们已经确保用户只能经过 WebP Cloud 代理链接访问到我们的图片了,接下来就是为图片添加版权水印。

webp_watermark_feature

同样是查阅了 WebP Cloud 的文档,发现它在「Visual Effects」模块中提供了「Watermark」功能,可以为图片添加自定义的水印,使用 Fabric.js 库实现,提供了可视化编辑的一些选项,还写了一篇有意思的博客 – 「使用 Fabric.js 实现实时水印预览」。

watermark_list_webp

进入 WebP 控制台,选择左侧「Visual Effects」,并点击右上角「Create Watermark」,就可以进行一些自定义水印样式配置了。

pseudoyu_copyright

这是我的配置,即在图片的底部中间添加一个浅灰色的 @pseudoyu 字样。

webp_purge_all_cache

需要注意的是,WebP Cloud 会为用户缓存图片数据,因此若想要之前上传的图片也应用水印或更新了新的水印则需要在代理配置中点选「Purge All Cache」来清理缓存。

apply_watermark_webp

编辑完水印后,进入代理的详细配置页面,下拉到「Watermark Setting」模块,选取刚创建的水印,点击右上角「Save」即可。

效果就不单独展示了,本文所有配图都通过这种方式添加了水印。

总结

webp_thoughts

使用 WebP Cloud 才第三天,最开始一直以为只是一个类 CDN 图片加速访问工具,经过折腾后发现了很多有意思的地方,并且为个人免费用户提供的 Free Quota 足够到大家拥有更好的图片体验,也就是他们所坚持的「做正确的事」。

团队更多是做一些技术沉淀和实践,写了许多博客 – 「WebP Cloud Services Blog」,闲时读读也能感受到他们的热情,最近因为「周报 #63 - 不愉快的订花经历、商家和消费者与日渐 AI 化的人」这一篇中的经历而在思考「劣币驱逐良币」这一问题,我觉得坚持做正确的事不向商业做过多妥协的团队理应被更多人看到,理应过得更好,我人微言轻,仅以这些教程来让更多的人了解到他们。

当云服务器崩溃时,我是如何救援重要数据的

前言

周五的时候我在搬瓦工平台购买的 2C2G 服务器突然内核报错,连不上 ssh 也 无法重启。经过了迂回的各种抢救方案,终于救回了一千多张图床的的图片,心有余悸,记录一下救援过程,顺便折腾了一套新的图床方案。

服务器救援

这台服务器大约已经稳定运行了一年半,运行了我许多重要服务,还有我博客图床的一千多张无备份的图片通过 Docker Volume 持久化在主机上。

服务器宕机

其实我至今仍不知道出了什么问题,早上刚好需要更新服务器上的我运行的 RSSHub 实例的镜像版本,于是想着干脆把所有服务都更新到最新吧,于是一通 docker pulldocker-compose 重启操作,前面的都没什么问题,直到最后一个服务突然启动容器失败,报了一个类似 not enough space 的错误,我心想着可能是下载的镜像太多了导致磁盘满了,于是又一通 docker image prune --alldocker volume prunedocker system prune 操作,释放出了接近 10G 的空间,重试,依然不行。

作为一个有且仅有一点服务器运维经验的开发来说,我第一反应想到的就是重启,未曾想,这才是一天噩梦的开始。

uptime_kuma_status

没想到重启后我的 Uptime Kuma 提醒我所有服务都下线了,也无法再通过 ssh 连上机子了。

bwg_kernel_panic

于是赶紧登录到搬瓦工的线上控制台,发现内核报错,无法启动,强制重启也依然不生效,于是先提交了一个工单,并且赶紧求援我的 DevOps 朋友们。

拯救数据

ask_strrl_about_vps

STRRL 说应该 rootfs 出现了问题,不过鉴于这种小云厂商并没有提供什么高级启动等额外的功能,只能等官方技术支持处理了,但想到我有一年半毫无备份的图床数据在上面,依然很慌,于是开始想办法抢救数据。

bwg_vps_snapshot

研究了一下搬瓦工的控制台,发现它提供一个大约每周一次的备份,并且可以一键将备份转为快照,最近的一次在 6.22 日,还好。我首先想到的是直接通过快照恢复机器,如果是我今天的操作导致了什么配置问题,那理应一周前的快照是能正常启动的,于是满怀信心地等待了十几分钟的快照恢复,结果报了同样的错误。依然不死心,把 6.15 的备份也恢复了一下,还是不行。

这下意识到了事情的严重性,甚至做好了数据全部丢失的最坏打算,但在等待工单回复时开始检索类似情况,最后发现搬瓦工机器的快照镜像是可以下载的,并找到了一篇「搬瓦工备份快照镜像文件 .tar.gz 下载解压后打开 .disk 文件查看数据教程」。

于是先下载了快照镜像,得到了一个 .disk 文件,这个文件应该是一个专属格式,看教程可以通过 Virtual Box 的命令行工具 vboxmanage convertfromraw 来进行格式转换,但官网下载后发现并不支持 M 芯片的 Mac,于是又在之前的老 19 款 Intel Mac 上安装并且执行转换,得到了一个 .vmdk 文件。

转换完成后将这个 .vmdk 作为一个磁盘挂载到 Virtual Box CentOS 虚拟机上,发现依然报同样的错误。

7zip_format

于是另辟蹊径,发现 7-Zip 软件支持常见虚拟机格式的解压,但客户端只有 Windows 版本。

x7z_vmdk_x

虽然按理说可以在 macOS 上使用命令行版本 p7zip 来执行,但我解压时会报错,所以又堵住了一条路,想了个曲线救国的方式,通过虚拟机下载了一个 Win11,下载了 7-Zip 软件直接解压成功了。

fuse_load_img

问题又来了,得到的是 1.img2.img 这样格式的 Linux 磁盘镜像文件,macOS 上无法加载,又问了我司运维朋友,折腾了一下 fuse 但是还是无法加载。

ufs_load_img_log

期间倒也是有好消息,在全网搜罗的时候发现了一个数据恢复软件 UFS Explorer,尝试了一下可以正常加载,只是超过 768k 的文件则需要付费,当然没打算,只是看到文件确实是可以识读之后心里就安心了许多,至少数据还在,剩下都是技术问题了。

bwg_reply

期间搬瓦工的工单也回复了,让我重启或重装试试。。。🤣

str_orbstack_img

放弃了工单沟通,继续抢救我 img 中的数据,万能的 STRRL 告诉我 OrbStack 可以启动一个 Linux Machine,然后可以把这个 img 作为一个 Linux 磁盘挂载上去。

sudo losetup -fP 1.img
mkdir /mnt/bwg
sudo mount /dev/loop0 /mnt/bwg

通过以上命令成功把我的 img 磁盘镜像挂载到了 OrbStack 的 Ununtu 机器上。

rescue_image_from_bwg_img

当我看到我的图片出现在命令行输出结果时,感动得都快流泪了 😭。

tar -czvf cheverto_chevereto_images.tar.gz cheverto_chevereto_images/
rsync -acvP ./cheverto_chevereto_images.tar.gz pseudoyu@[yu-mac-studio]:~/Downloads/

rsync_service

紧接着赶紧打个 tar 包,然后通过 rsync 传到了我本地的 Mac 上,本机解压后,终于看到了我所有的图片。

迁移图床系统至 r2

但由于这一次的遭遇,不再信任服务器单机部署的图床稳定性了,花了半天折腾了一套新的免费图床系统 —— 「从零开始搭建你的免费图床系统 (Cloudflare R2 + WebP Cloud + PicGo)」。

rclone_service

至于现有的数据传到 r2,我则是使用了 rclone 来进行上传,彻底完成迁移,大功告成!

总结

也开始重新考虑了服务部署、数据安全等问题,准备还是将一些重要的数据上云而不再依赖单机,也继续把一些服务迁移到 fly.io、Zeabur 等 serverless 平台。

周报 #63 - 不愉快的订花经历、商家和消费者与日渐 AI 化的人

《Photograph - Ed Sheeran》

前言

weekly_review_20240701_new

本篇是对 2024-06-242024-06-30 这周生活的记录与思考。

一次不愉快的订花和维权体验,思考了商家与消费者的关系,以及 AI 越来越拟人化的现在,人却似乎变得 AI 化了的现象;周五的时候服务器突然 Kernel Panic,无法重启,经过了迂回的各种抢救方案,终于救回了一千多张图床的的图片,心有余悸,顺便折腾了一套新的图床方案;想到上一次写博客搭建教程已经是两年多前,不论是内容还是组件都经过了许多变化,于是重新开启系列。

一次不愉快的订花经历

refund_flower

周末发生了一件非常不愉快的事(甚至现在依然还因商家拒绝上门取货而处理中)。

6 月 30 日是我和学姐在一起一周年的日子,我早上在饿了么外卖平台订购了一束花,原本是一件挺开心的事,结果送到学姐那的时候,花上还附了一张卡片,上面写着“to 小语宝贝”和一些私人的祝福,但我并没有要求附赠卡片。

想来是放错了卡片,所幸收货时我也在现场,不至于引起什么误会或是矛盾,当时有些扫兴但也还不至多生气,于是联系了商家退货。

我跟商家描述了情况,表示理解可能是花艺师放错了,但因为送花本来就是情绪价值大于花本身的一件事,我并不想要这样一束似乎原意是“送给别人”的花了,然而商家的态度很恶劣。

“放错了你把卡片丢掉就好了”

“我又没做错为什么要退”

“那你联系客服维权好了”

我自诩是一个情绪稳定的人,也多少对身边的人和这个世界善意相待,不会为难因恶劣天气延误的快递员、送到的外卖洒了也从未要求小哥的赔偿或是退款,但依然被商家的态度气到了。

我可以理解花艺师的疏忽,也并不对花本身有什么不满,只是感到可悲,商家做的是“花艺”的生意,理应明白送花的人送的不仅仅是花,更多的是一份心意的传递或是情绪的表达,而她的态度让我感到这份心情并没有被尊重。

似乎对于这位卖花的店家来说,花只是花,是流水线上生产出的人工造物,送花人的忐忑、收花人的羞怯或是惊喜似乎都无关紧要。

当然,我理解这作为商业当然有成本和营收的考量,可这依然刺痛了我仍留存的几分理想主义,没有这些心情加持的花艺,再美丽也不过是一堆很快就会腐朽的有机物罢了。

商家与消费者

于是我联系了客服,一番沟通后才知道为什么商家那么有恃无恐。原来在饿了么平台上,花是属于无法退货的商品,我理解本意或许是由于鲜花是人工制作的易腐商品,退货后也无法二次销售。

我联想到前一阵子关于消费者利用拼多多平台“仅退款”机制伤害商家的争议,这次经历又何尝不是商家在利用平台规则来伤害消费者呢?

人的 AI 化现象

这事还没结束,和饿了么客服的对话更是让我有些无语。

我:(再一次详细描述了情况以及商家的态度问题),我想要申请退货,但商家拒绝了

客服:请问花是没问题的对么?

我:…你要这么说可能也没错,但我不想要了。

客服:我们鲜花按照平台政策是不能退款的呢~

我:但附赠了给别人的卡片,这不是我想要的花。

客服:那我联系商家给您重新发一张卡片可以么?

我:…

我现在还对这段对话有些哭笑不得,都说 ChatGPT 出来之后 AI 越来越像人了,AGI 或许也不远了,但我倒是觉得在此之前,人是越来越 AI 化了,似乎对于他们来说把对面当作一个有情绪有脑子的人看待都已经是一件很难的事了。

有时候我常常会思考现在的人是怎么了,以制作鲜花为业的人不好好对待花,也无法设想如果自己收到爱人送的一束写着别人名字的花的不良情绪;以解决用户问题为业的平台客服不好好听用户讲话,只知道模板化地回复。

flower_from_beijing

想起在北京时长期会订的一位花艺师,因为是定制花束,比起平台上的贵上许多,但会问问我的故事和想要表达的情感,会记得我们把花放在花瓶的习惯,也能将我各种对花的小想法一一实现。当时只是对花艺师小姐姐的用心印象深刻,现在才发现,好好讲话,用心做好自己的工作,原来在当今社会已经是一件需要奢求的事了。

那是一家并不大的店,从配货、选花、做花到配送只有店主一个人,而我这次订的这家在杭州算是个网红店,常居各种平台榜首,销量 9000+,劣币驱逐良币,真是悲哀。

有趣的事与物

博主

落拓学长回来了!!!四五年前一直看他的视频,甚至人生走向都是沿着他当时说有些遗憾自己未选择的区块链方向,一直以他为目标。

后来他转行 fintech,去了 Jane Street,这几年也不断在选择新的挑战,慢慢停更了。回来后聊了学习成长、焦虑与冒名顶替综合征,这些也都是这几年慢慢步入工作的我开始思索的东西,依然有被激励到!

这就继续学 Rust 去了。

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。

书籍

  • Normal People,很喜欢这个英剧,这两天看其他书的时候突然想到了这本,打算补一下原著。
  • What My Bones Know,去年看了一小半,这两天想到关于家庭和心理疗愈的问题,每天看一章左右。
  • 阿特拉斯耸耸肩,读者送的,读了前两张章了。

文章

视频

从零开始搭建你的免费图床系统(Cloudflare R2 + WebP Cloud + PicGo)

前言

在「2024 年了,我的博客有了什么变化」一文中,我介绍了自己使用 Serverless 平台和一些开源项目搭建的博客系统,也开启了这个系列教程来记录搭建和部署全过程。

本篇是关于图床系统的解决方案。

[2024-07-02 更新]

新写了一篇教程实现了图床添加隐私和版权保护,算是番外篇。

图床方案迭代

其实在博客搭建之初因为内容并不多,也比较少有插图,所以大部分的图片都是直接放在我的 Hugo 博客仓库的 static 目录下,也没觉得有什么不便,直到有一段时间需要多平台发布,复制了博客的 markdown 源文件后,因为所有图片都是博客的相对路径,导致图片全部无法显示,需要把图片一张张重新上传,十分繁琐。

那时才开始了解到图床(Image hosting)这个概念,把图片上传到一个专用的存储服务并通过公开链接使用,不但可以统一进行管理,还能有效减少博客仓库文件的体积,提高网站的加载速度。

GitHub + jsDelivr CDN + PicGo

一开始我是新建了一个 GitHub 仓库「GitHub - image-hosting」,通过 PicGo 直接上传到仓库,并在 PicGo 返回时的图片路径改为 jsDelivr CDN 加速后的链接,其实倒也还算方便,还多了一份版本管理。

不过好景不长, jsDelivr 遭到了 DNS 污染,被大陆封锁,以至于我的博客图片在很长一段时间完全无法加载,也让我对这种纯依赖 CDN 的方式有了一些顾虑,再加上 GitHub 托管图片是基于代码仓库,上传图片依赖的是代码提交,容易污染 commit 记录,且终究算是一种滥用,万一账号/仓库访问有问题也容易丢失所有图片,于是开始寻找其他方案。

阿里云 OSS + PicGo

第二个想到的就是云服务商提供的对象存储了,像是 Amazon S3、阿里云 OSS 等都是云厂商提供的对象存储服务,在提供可访问的公开链接的基础上还多了权限控制、数据备份、拓展性等优势,在相对低成本的前提下提供了针对文件数据存储和管理的较优解决方案。

由于是想针对中国大陆用户进行访问优化,最终我选择了阿里云 OSS,配置不算复杂,同样是通过 PicGo 进行上传并转换为阿里云 OSS 的链接,在访问速度上有了明显的提升。

aliyunoss_invoice

不过由于多是按量计费,持续增长的成本对于非盈利的个人博客来说也是需要考虑的。23 年初有一阵子博客流量较大,月账单持续上涨,再加上阿里云 OSS 如果需要自定义访问域名则需要进行备案,我域名本身通过 Cloudflare 进行托管,并不考虑备案,所以在用了几个月后,还是考虑更换图床方案。

Chevereto + PicGo

经过了一番调研,在我线路不错的搬瓦工服务器(CN2GIA DC6 机房)上使用 Docker 镜像部署了 Chevereto 的免费自部署版本,并将图片以 Docker Volume 的形式挂载在主机上。

Chevereto 的界面实话说风格有些老旧,还是古早的 php 服务,免费版也很久就不再维护升级,但胜在功能完备,同样可以使用 PicGo 对接 Chevereto 的 API 进行图片上传等操作,稳定性也不错,于是就这样用了一年半。

但自己对于自部署服务的稳定性和数据的珍贵性还是有些大意,前几天服务器突然挂了,内核报错直接无法重启,服务挂了倒还好说,但是我这一年半多的图片数据也无法导出,工单联系技术支持,一天只回复了我两次,一次让我重启,一次建议我聘请一个网络管理员排查。

只能自力更生,翻遍了网上各种方案,折腾了一天终于算是解决了,但这一次的教训让我对有重要数据的服务备份和自部署稳定程度都有了全新的认识,再加上想要重新部署的时候发现免费版镜像等已经下线,只剩一个按年付费的 License 版本,于是放弃了原方案。

Cloudflare R2 + WebP Cloud + PicGo

cloudflare_r2_free_tier

于是重新转向了云服务厂商的对象存储,发现了赛博菩萨 Cloudflare 提供的 R2 对象存储这一服务,免费计划中有每月 10 GB 的存储容量,对于个人使用来说完全够用,大厂的服务与数据安全也有保障。

为了优化用户的访问,又使用了一个「WebP Cloud」服务对 R2 的图片进行代理,在代理层面进一步减小图片体积,虽然对于国内用户来说速度肯定还是比不上阿里云 OSS 这种线路,但是在不用备案、稳定且免费的综合条件下,这是我能想到的最好的方案了。

在电脑端同样是通过 PicGo 客户端几乎一键上传并生成博客直接可用的 markdown 图片链接,配置完成后使用起来很顺滑。

图床搭建说明

Cloudflare R2 + WebP Cloud + PicGo 的方案尽管牵扯到了多个组件和平台,但所有操作都在 Free Plan 中,也是我最终选定的方案,下面将从零开始介绍如何搭建这个免费图床系统。

Cloudflare R2

R2 是 Cloudflare 推出的免费对象存储服务,需要免费注册一个 Cloudflare 账号才能使用,注册登录后,点击左侧边栏的 R2 访问服务,但需要注意的是开通 R2 服务需要绑定信用卡(国内外主流信用卡皆可),但并不会扣费,主要是为了验证用户身份使用。

创建图床 Bucket

cloudflare_r2_interview

开通 R2 服务后,点击右上角「创建存储桶」按钮进行创建。

cloudflare_r2_create_bucket

进入创建配置界面后,需要填写存储桶(Bucket)名称,建议有一些辨识度,后续在配置上传时会用到。

位置则选择「自动」,但可以额外多配置一个位置提示,由于我后续还将使用「WebP Cloud」服务的美西机房进行图片代理优化,所以在此处选择的是「北美洲西部(WNAM)」,根据需求选其他区域也可以,但 Cloudflare 并不保证一定会分配到所指定的区域。

cloudflare_r2_create_done

点击「创建存储桶」按钮即完成创建,此时我们已经可以向我们的「yu-r2-test」存储桶上传文件了,可以选择在网页直接上传文件或文件夹。

也可以使用 S3 API 进行上传,我们后续使用 PicGo 客户端进行上传就依赖这种方式,但需要进行一些额外配置,点击导航栏「设置」选项进行配置。

cloudflare_r2_config

首先我们需要打开「R2.dev 子域」,这是为了后续访问图片时需要的公网地址,点击「允许访问」,并按照提示输入「allow」即可开启。

r2_dev_domain_allow

完成后会显示一个以 r2.dev 结尾的公网网址,即我们后续访问图片的网址。

自定义图床域名(可选)

但是分配的网址比较长,不易于记忆,我们可以通过「自定义域」来绑定我们的专属域名,点击「连接域」按钮。

r2_custom_domain_setup

输入自己想绑定的域名,如 yu-r2-test.pseudoyu.com,点击继续。

cloudflare_r2_custom_domain

r2_custom_domain_dns_wait

连接域,并等待 DNS 解析生效即可。

r2_bucket_status

完成后 bucket 状态处「公共 URL 访问」显示“已允许”,且「域」显示为我们刚自定义的域名即配置成功。

配置 Bucket 访问 API

yu_bucket_preview

当我们完成上述配置后,可以回到存储桶「对象」界面,上传一张示例图片,点开详情则会显示该图片的访问地址,此时我们就拥有了一个可访问的图床服务了。

但每次都要打开 Cloudflare 页面手动上传图片的方式显然不够便捷。R2 提供了 S3 兼容的 API,可以方便地使用一些客户端/命令行工具进行上传、删除等操作。

create_r2_api_token

create_r2_api_key

回到 R2 主页面,点击右上角「管理 R2 API 令牌」,进入后点击「创建 API 令牌」。

r2_apikey_conifg

输入令牌名称,「权限」选择“对象读和写”并将此 API 指定之前所创建的 Bucket,这样最小化权限也保障数据安全,其余选项保持默认即可。

api_key_config_details

完成创建后会显示所有密钥,我们使用 PicGo 需要的是下面三个信息,不过因为只会显示一次,建议在密码管理软件或其他地方妥善保管好这些参数信息。

至此,我们需要在 Cloudflare R2 上配置的部分就完成了,接下来我们需要配置 PicGo 客户端。

PicGo

PicGo 是一个用于快速上传并获取图片 URL 的工具软件,有着较为丰富的插件生态,支持多种图床服务,其 GitHub 仓库为「GitHub - Molunerfinn/PicGo」,可以下载对应平台客户端使用。

配置 R2 图床

PicGo 本体并不包括 S3 图床,但可以通过「GitHub - wayjam/picgo-plugin-s3」插件来支持。

picgo_s3_plugin

在「插件设置」中选择安装,「图床设置」中就新增了 Amazon S3 选项。点击进入配置选项。

r2_picgo_s3_config

这里有几项配置需要尤其注意。

  • 应用密钥 ID,填写 R2 API 中的 Access Key ID(访问密钥 ID)
  • 应用密钥,填写 R2 API 中的 Secret Access Key(机密访问密钥)
  • 桶名,填写 R2 中创建的 Bucket 名称,如我上文的 yu-r2-test
  • 文件路径,上传到 R2 中的文件路径,我选择使用 {fileName}.{extName} 来保留原文件的文件名和扩展名。
  • 自定义节点,填写 R2 API 中的「为 S3 客户端使用管辖权地特定的终结点」,即 xxx.r2.cloudflarestorage.com 格式的 S3 Endpoint
  • 自定义域名,填写上文生成的 xxx.r2.dev 格式的域名或自定义域名,如我配置的 yu-r2-test.pseudoyu.com

其他配置保持默认即可,确认参数无误后点击「确定」与「设置为默认图床」即可。

图片上传

upload_r2_with_picgo

完成上述配置后,我们就可以在「上传区」直接拖入文件进行图片上传了,如上传后显示无误则为配置成功,生成的链接会自动在系统剪贴板中,直接在需要的地方粘贴即可。

picgo_custom_url_format

并且可以在链接格式处选择对应格式,如 URL 或是博客可用的 Markdown 格式链接等。这里我还做了一个小的配置,在左侧「PicGo 设置」 - 「自定义链接格式」中修改为 ![$fileName]($url),并在上传区的链接格式处选择了「Custom」,这样我上传后就会根据文件名生成以文件名为 Alt 文本的 Markdown 图片链接。

WebP Cloud 图片优化

至此我们已经完成了整个图床的搭建、配置和上传,但通常我们本地截图或是相机拍摄的图片体积较大,对于访客来说加载时间会较长,并不直接适合互联网发布。

tiny_png_compress

我在很长的一段时间都用了非常笨的方法,即「TinyPNG」这一在线网站的 api 配合一个开源的 macOS 客户端应用,将图片拖入其中进行压缩后再通过 PicGo 上传到图床,通常能够在图片质量损失较小的前提下减少图片 50% 以上的体积,繁琐却有效。

这次更换图床方案后也开始寻找更智能的图片优化服务,想到了「WebP Cloud」。

其实了解到这一服务是去年的一个晚上和 STRRL 正在杭州一个商城的电玩城里看人打音游,他给我看了 Nova Kwok 的一篇博客上了 hacker news 榜首的消息,一起围观了半天,不过当时大概只知道是优化图片的服务,并没有详细了解。

于是又去打开了官网「webp.se」看了一下更为详细的介绍。

webp_se_intro

简单来说这是一个类 CDN 的图片代理 SaaS 服务,可以在几乎不改变画质的情况下大幅缩小图片体积,加快整体站点加载速度。发展到现在除了图片体积减少外,还提供了缓存、添加水印、图片滤镜等更多实用的功能,并提供了自定义 Header 等配置选项。

看了一圈,觉得能很好满足我的博客图片优化需求,开始折腾配置。

配置 WebP Cloud

webp_cloud_login

首先通过 GitHub 授权登录 WebP Cloud 平台。

webp_cloud_overview

页面非常直观,主要显示了当前 Plan 下的 Free Quota 和额外 Quota 的数据,以及一些用量统计。

点击「Create Proxy」按钮可以添加配置。

webp_cloud_config

  • 为了优化国内访问,我「Proxy Region」选择的是美西「Hillsboro, OR」区域
  • 「Proxy Name」填写一个自定义名称即可
  • 「Proxy Origin URL」,比较重要,需要填写上文我们配置好的 R2 自定义域名,如我填写的是 yu-r2-test.pseudoyu.com,如果没配置自定义域名则填写 R2 提供的 xxx.r2.dev 格式的域名

yu_webp_test

图中 Basic info 部分「Visitor」下显示的以 xxx.webp.li 格式即为我们的代理地址。

例如我们之前通过 PicGo 上传到 R2 的文件 yu-r2-test.pseudoyu.com/new_mbp_setup.jpg 则可以用 dc84642.webp.li/new_mbp_setup.jpg 这一链接进行访问。

如果不喜欢默认的代理地址,则可以右下角 Chat 或是邮箱联系开发者进行自定义域名修改,之后或许也会有更自动化的配置流程。

[2024-07-06 更新]

支持了自定义配置域名,详细教程可参考「Custom Domain | WebP Cloud Services Docs」。

更改 PicGo 配置

change_pic_go_config

需要注意的是,由于我们最终需要放在博客中的图片是经过 WebP Cloud 代理过的链接,所以需要回到 PicGo 的「图床设置」中,将「自定义域名」改为我们刚配置的 WebP Cloud 代理地址,即格式为 xxx.webp.li 的代理链接或其他自定义域名。

WebP Cloud 用量

免费用户每天有 2000 Free Quota,即能够代理 2000 次图片访问请求,并提供 100M 的图片缓存,对于一般用户来说完全够用,如有一些流量较大的特定时期也可以购买额外 Quota,价格很便宜。

如超过了 Quota,访问则会被 301 转发到源站图片地址,不经 WebP Cloud 服务压缩,但依然可用;超过 100M 的缓存则会按照 LRU 算法清理,所以依然能够保障一些高频请求的图片能够有较好的访问体验。

yu_webp_uasge

我博客的日访问量大概在 300-500 visits 左右,再加上一些 RSS 订阅和爬虫的流量,根据 WebP Cloud 统计测算来看,平日的请求大概在 4000-5000 次,发博文当天会有 10000+。

webp_cloud_price

所以目前先选择了 Lite 计划,配合一些额外用量来 Cover 高峰流量,打算再观察一阵子看看。

总结

以上就是我的图床系统搭建方案,本文的所有图片也都使用 PicGo 上传、Cloudflare R2 存储并经 WebP Cloud 代理优化。

这是我的博客搭建部署系列教程之一,如对评论系统、数据统计系统等搭建感兴趣,请持续关注,希望能对大家有所参考。

2024 年了,我的博客有了什么变化

前言

在两年前的这一篇「2022 年了,聊聊我为什么还在写博客」,我聊到了我写博客的缘起、初衷和搭建方案。

两年多过去了,初衷仍在,写作也依然坚持下来了,虽没有完成自己所计划的周更,但多少也积淀了些文字。

经历了很多事,似乎渐渐转向了一个「周报博主」,写的内容和风格已经大不同。技术和工具效率主题更少了,分享生活和思考更多了;少了些通宵两天更新四篇技术教程的冲劲,却多了些通过笔触表达情感后的自洽;收到很多关于博客搭建和技术教程的感谢依然会很开心,却也更珍惜和素昧谋面的大家交心的感动。

周报博主

可能是有一次开会闲聊 xLog 未来的发展,有位同事突然 cue 我说,你作为一个「周报博主」有什么想法,我一愣,这个称呼倒是第一次听到,翻了翻主页,确实。

之前一直自诩是技术博主、工具效率博主,最后留下内容最多,给大家印象最深的似乎还是周报,也不错。

weekly_review_group_chat

开始写周报似乎是「Homura」组织了一个周报监督小组,当时不论是在推特还是独立博客群体中都还是个小透明,也希望有更多人进行抱团和交流,当时会每周把自己的周报丢到群里,会有互相被卷到,也有对于他人生活状态的关心,很开心。

后来大家都经历了许多生活的工作的变动,群里最后的消息停留在了 23 年 1 月,但那依然是我很快乐的一段时光,也是我后来能继续写周报的动力,因为我知道,即使分享的只是生活的琐碎和一些不成熟的小想法,依然有人在认真读你的文字。

weekly_view_discuss_with_randy

之前有一次收到 Randy 的催更,他说其实没必要把它定义为周报,不然常常会有压力和束缚,不过我反倒依赖这种输出倒逼输入的模式,这样有了周报作为一个结果导向,才会更有动力把这周过好。

虽然我常常重新定义周就是了。

独立博客

比起编排精美的书刊杂志,我更享受于访问他人的博客网站,站名名称、主题配色、配乐排版都更真实具体地呈现了一个人格化的存在,而在阅读博文时,我也常常会视为一次穿越时空的对话,会想象写下这些文字碎片的作者当时是怎样的心情,有时甚至也会带些顽皮地脑补他是一个怎样的人,此刻在做些什么。

独立博客其实是一个说大不大说小不小的圈子,两年过去,我反倒觉得开始搭博客、写博客的人渐渐变得多了,也有了更多有意思的高质量内容。

相比起其他不论是粉丝积累还是互动都更为方便的成熟内容平台来说,不仅仅是平台和写作形式上的独立(我其实也愿意称在 mastodon 或是 misskey 上认真分享内容的人为独立博客作者),而是思想的独立,即好的文章不止授人知识,还引人思考。

dubo_1_intro

还跟 Randy 聊到想为独立博客做一些事,以刊物的形式收录这一段时间内读到的好的文章并为之作序推荐,其实已经筹备好了第一期,但由于两个人错峰的忙碌和更专注地做 EpubKit 产品,迟迟未能发布,这也是希望能够在未来某个节点能够持续做下去的事。

博客系统

这是两年前写过的几篇关于博客搭建的文章:

主要是围绕着我使用 Hugo 这一静态网页生成器(SSG)搭建个人博客及一些周边服务的一些记录,也看到很多人通过各种联系方式加到我说根据这一系列教程成功拥有了自己的博客,很开心能够为博客这一已经有些式微的创作方式做出一些小小的贡献。

当时写的时候对自己的整套方案很满意,然而时隔两年回头看了下。

  • 博客本体:Hugo 本体没变,部署方案: GitHub Pages + Cloudflare CDN -> Cloudflare Pages
  • 评论系统:Cusdis -> Remark42,部署平台:Railway -> Vercel + Supabase -> fly.io
  • 统计系统:Umami -> goatcounter,部署平台:Vercel + Heroku -> Railway -> Netlify + Supabase -> fly.io
  • 图床系统:GitHub + jsDelivr -> 阿里云 OSS -> VPS 上自部署的 Chevereto + PicGo -> Cloudflare R2 + WebP Cloud + PicGo
  • 内容搜索:无 -> Pagefind 静态搜索

更换的原因很多,有些是由于 Heroku 和 Railway 渐渐取消了免费计划,有些是由于开源项目更新少了缺少功能,也有些单纯是自己想折腾一下更轻量些。

想起来当时写这套系列教程的时候主要就是觉得网上能够搜到的方案和教程零散且常常落后,于是想给想搭建博客的读者一站式搭建起来的可行方案,发布后收到了许多人的反馈,有些内容也早该更新,却一直拖到现在才开始重新写,很惭愧。

下文会对当前的方案作一些介绍,后续更新后的系列文章完成后也会追加链接。

博客本体

yu_blog_homepage_20240629

我使用 Hugo 这个静态网站生成器来搭建我的个人博客,使用并改造了一个比较 retro 的主题「hugo-theme-den」。

大体的流程可以参看「Hugo + GitHub Action,搭建你的博客自动发布系统」这篇文章和「GitHub - yu-blog」这个仓库。

加了一些每天自动更新 About 页面的 GitHub Actions 自动化操作,并且由于 GitHub Pages 托管的网站从国内访问速度几乎不可用了,迁移到了 Cloudflare Pages,免费且体验感好了很多,其他几乎没什么改动了。

其实倒也不是没想过换框架,之前看到「Owen」和「PJ Wu」使用的 Zola 就有些眼馋,甚至也有想过像「槿呈 Goidea」或是「Innei」一样自己写一个。

不过冷静下来一想,自己现在网站积累了不少文章,要是想要保留原有路径免不了一番折腾,再加上确实很喜欢现在的主题,有什么想法干脆就直接去定制和改动主题了,还是少花一些心力在折腾平台,多写些博文比较重要,不然多少有点买椟还珠之嫌,遂作罢。

评论系统

在博客诞生之初直到今年四五月我一直使用的都是 Cusdis,整整用了三年。

时至今日依然是十分值得推荐的方案,轻量,方便自部署,风格也简约好看,搭建教程参看「轻量级开源免费博客评论系统解决方案 (Cusdis + Railway)」。

不过鉴于 Railway 从去年 8 月起已经取消了 Free Plan,如果依然想完全免费使用,可以使用 Vercel/Netlify/Zeabur 免费部署主项目,并在 Supabase 上部署一个免费的 PostgreSQL 数据库实例,把链接作为环境变量传入 Cusdis 服务中即可,其他流程大同小异。

yu_remark42_preview

最近有一次由于更换数据库 URI 时 Vercel 部署一直报错,再加上确实需要一些新的功能,于是下定决心从 Cusdis 迁移,调研了一圈后选择了 reorx 在「更换博客评论系统」一文中最后选定的 Remark42

单纯就配置选项来说比起 cusdis 还是丰富了不少,目前配置了常用的几种社交账号登录(GitHub、Twitter、Telegram、邮箱)、可以匿名评论、支持邮件订阅回复提醒并且也设置了 TG bot 提醒,并且部署在 fly.io,go 单二进制 + 数据库单文件,很舒服的解决方案,完成博文后会在这里更新教程链接。

[2024-07-22 更新]

评论系统搭建详见这篇。

数据统计系统

我之前自部署了一个 Umami(参看教程「从零开始搭建一个免费的个人博客数据统计系统(umami + Vercel + Heroku)」不过后来由于 Heroku 取消了免费 Plan,我最后折腾一圈,选择了 Netlify 部署服务 + Supabase 部署 PostgreSQL 数据库实例部署的方式,其余流程依然适用。

yu_goatcounter_preview

不过一方面因为我部署得比较早,有一个大版本无法升级,以至于一直停留在自己 fork 的一个旧版本上,另一方面确实也渐渐觉得这种服务和数据库需要分离的方式免不了因为平台规则变动而频繁迁移,有些太重了,所以最后改为了 goatcounter,同样是 go 单二进制 + sqlite 数据库单文件部署在 fly.io,又是很舒服的部署方案,等更新博文后同样会在这里更新教程链接。

yu_google_console_preview

另外就是依然使用 Google Console 来统计分析我的访客信息与搜索权重。

这个结果很有参考性,我发现一篇关于终端对比的文章「Warp,iTerm2 还是 Alacritty?我的终端折腾小记」让我持续不断地有通过搜索引擎来的访客,另外的就是关于个人博客和搭建的系列文章了。

[2024-08-06 更新]

网站数据统计系统搭建详见这篇。

图床系统

两年前我其实还没怎么关注图床的问题,图片都是直接丢在 GitHub 仓库里,并且使用 jsDelivr 作为 CDN 加速(后来国内访问也几乎不可用了),不过随着文章数量增多,常常有身边的朋友告诉我说我的博客图片加载不出来,想着还是要兼顾一下阅读体验,于是调研了一圈方案。

aliyunoss_invoice

先选择了阿里云 OSS 存图,电脑使用 PicGo 上传,方案挺好的,前几个月也没什么问题,直到 23 年初有几篇文章流量比较大,看着月账单上涨的势头,顿感贫穷。

于是在线路还不错的搬瓦工服务器上自建了 Chevereto 图床,同样配合 PicGo 的插件进行上传,稳稳地用了一年半。但自己对于自部署服务的稳定性和数据的珍贵性还是有些大意,前几天服务器突然挂了,内核报错直接无法重启,服务挂了倒还好说,但是我这一年半多的数据没有备份,也无法导出。

工单联系技术支持,一天只回复了我两次,一次让我重启,一次建议我聘请一个网络管理员排查。只能自力更生,翻遍了网上各种方案,折腾了一天终于算是解决了,但这一次的教训让我对与有重要数据的服务部分和自部署稳定程度都有了全新的认识,于是不敢再用原方案。

yu_webp

最后采用了 Cloudflare R2 对象存储来存放图片,每个月 10G 的免费额度很足够,大厂的服务与数据安全也有保障。为了优化用户的访问,又使用了一个「WebP Cloud」服务对 R2 的图片进行代理,在代理层面进一步减小图片体积,虽然对于国内用户来说速度肯定还是比不上阿里云 OSS 这种线路,但是在不用备案、稳定且免费的综合条件下,这是我能想到的最好的方案了。

yu_picgo_pics

在电脑端通过 PicGo 客户端几乎一键上传并生成博客直接可用的 markdown 图片链接,配置完成后使用起来很顺滑。

图床搭建教程见这篇:

[2024-07-02 更新]

新写了一篇教程实现了图床添加隐私和版权保护,算是番外篇。

内容搜索

search_in_my_blog

之前我的博客是没有内容搜索功能的,本来文章也不多,再加上静态博客没有后端,实现起来感觉也不容易,于是一直没支持。但随着后来有时候要查阅自己之前的文章只能用 VS Code 在一堆 markdown 文件中搜索的体验后,觉得还是很有必要的。

调研了一圈使用了 Pagefind 这一项目,基于静态文件的搜索库,无须引入或是托管其他后端服务,我只需要在每次发布博客的 CI 中构建全博客的索引文件,就能够很方便地支持搜索,中文搜索效果相对弱一些,不过也是够用的程度,基本上对主流的博客框架都支持。

这部分可以参照「如何透過 Pagefind 在 Zola 產生的靜態網站裡加入搜尋功能」这篇文章。

总结

2024 年了,我大抵还是个爱好写作的人,从早些年的书评影评、技术教程到现在的生活周记,似乎所见所思只有落笔写下才会转为触手可及的真实。而随着上百篇文章的沉淀,个人博客站点也成为了我在这世界的另一个载体,源于我却又独立于我,有时是随手可拾起的记忆碎片,有时又是自己精神的避难所。

也希望你们能够继续在我的博客中发现一些有趣的东西,或是知识,或是启发,抑或是一点点小小的共鸣,或许在某个时刻,你们也会想拥有自己的博客站点,让自己的所思所想在这个世界上留下一些痕迹,生根、发芽,也希望这套系列教程能够提供一些帮助。

周报 #62 - 香港之行、5am club 计划与 Rust 学习

《Photograph - Ed Sheeran》

前言

weekly_review_20240623

本篇是对 2024-06-172024-06-23 这周生活的记录与思考。

去香港参加 Google AI+Web3 活动,面基了组里的很多小伙伴;体验了因订不到房而露宿网吧;打算根据 5am Club 理念调整生活节奏;第二次入门 Rust;还有很多有意思的事。

香港之行

henry_and_kate_at_google

这周最有意思的事是去香港参加了 Google 的 Web+AI 的活动,我们项目在其中有一些 talk 和圆桌论坛,刚好也有机会参观了 Google 的香港办公室(以及拿了一些周边)。远程办公之后,其实比较少能有机会和同事们面对面,而这次活动我们组除了一位在美国的同事没法赶到外,其他人都相聚香港,还一起聚餐、打德州以及后面续了一场深圳漫步。

stay_netbar

很有意思的是由于我和杭州一同来的同事 ares 没有提前订好房,直到零点之后在铜锣湾时代广场四处找酒店,最后选择了去露宿网吧,刚好拿着从 Google 那边领的抱枕,倒也是挺好睡的。

突然想到之前在香港读书赶课程大作业的 due,当最后卡着 ddl 提交后,和小组成员一起买了一堆零食和啤酒在维港闲聊、看日出的经历;也想起之前和朋友去泰国,跟着 Pokémon GO 的地图四处解锁景点;以及去青岛旅行时让出租车司机随便开,带着我绕一圈有趣的地方,这些都是很有趣的人生体验。

我虽然是个 j 人,在大部分时候会制定严密的计划,但也非常享受这份生活的随机性,或许多年之后并不会记得这场 Google 的 talk 有什么有趣的发言,但一定不会忘记这一晚在网吧过夜的记忆画面。

5am club 计划

hangzhou_night

Robin Sharma 有一本书叫《5am Club》,提出了一个早上五点起床,进行自我提升学习、锻炼以达到最佳状态的概念,虽然对于经常熬夜到三四点甚至更晚的我可能 5am 睡更容易达到,不过依然对这种新的生活方式有些憧憬。

大学有过很长一段时间的极端自律,每天一两点睡、六七点起,似乎有着用不完的精力和时间,在香港读研期间也由于跨专业的焦虑和课业压力,每天六点多起床去图书馆占座,接近 11 点才回到租屋,循环往复却也乐在其中。

但大概是由于工作之后白天的许多时间天然被占据,似乎这样的习惯很快被打破了,为了有更完整的自己的时间,更晚睡,却也更晚起。有阶段性会保持不错的状态,但也容易陷入一些不好的循环,晚上学习状态不好 -> 焦虑 -> 报复性熬夜 -> 第二天起床更晚 -> 白天效率低下 -> 晚上学习状态更不好。

于是想从这周开始进行一下尝试与挑战,倒不一定是严格的五点,只是相对更早,把熬夜的学习时间平移到早上,一直到 11 点左右调整到开始上班的状态。

而由于被隔壁 「polebug」 的 study vlog 卷到,也有了一些尝试新领域的学习动力,所以也给自己定了更加有趣的目标,早上最开始学习的是一些跟工作并不直接相关但一直想体验的东西,比如 SwiftUI、Rust 以及使用 langchain 进行一些 AI 应用的开发实践等等,这次也打算直接 learn by getting hands dirty,直接上手一些 side project 或是给开源项目贡献 pr。

Rust 学习

rust_bag_2023

承上文,打算第二次入门 Rust,上次入门还是在 22 年,其实还挺认真地学了一阵子,跟着写了一些 demo 项目,还做了学习笔记「pseudoyu/learn-rust」,不过确实工作里没有应用场景,已经忘得差不多了。

组里有个 Rust 狂热爱好者 kally,香港和深圳之行一路在推荐,甚至在我上飞机前还让我下了 YouTube 上的入门视频,确实挺好睡的

不过正经地打算重新学习一下,也上手写一些自己的项目,目前的想法是把之前一个通过 RSSHub 来订阅多个平台信息源同步的 go 项目通过 rust 重写一下,以及看看有没有什么好玩的开源项目可以参与。

目前在看 kally 推荐的一些 YouTube Channel 的基础视频,以及很久之前买的极客时间的「Rust 编程第一课」,Rust,启动!

Telegram Channel 1000 subscribers

channel_1000_subscribers

频道 1000 subscribers 达成!感觉越来越少在推或者其他平台上表达,更喜欢在频道里碎碎念了。

其实分享欲这个东西一直存在,有时候是与自己对话,有时候是和身边的人秉烛夜谈,又有更多的时候想分享给更多人得到一些反馈,只是关闭朋友圈的我似乎已经不太习惯将这些分享到我的周围,所以有很长一段时间 twitter 成为了这个出口,而这一年,博客的读者和频道的关注者才慢慢成为分享的对象,感觉其实现在的节奏下似乎好好听人说话、思考并回应似乎成为了一件弥足珍贵的事,我也时常告诫不要忘记这一点。

也谢谢你们好好听我讲话。

其他

mac

new_mbp_setup

新拿到的 Google Cloud 贴纸贴上了我的 MBP,集邮了!

周中发现 mac 出现了灵异事件,当 slack/zoom 等软件打开麦克风时光标就不受控制,以 2-3 秒一次的频率点左上角菜单栏,像是被远程控制了一样,且其他时候一切正常,去了 Apple 和技术支持小哥一起排查了好一会儿定位到了是新安装的 Bartender 的替代品 iBar 导致的,据评论区说 Barbee 也有这个问题,大家可以参考一下 🫡。

小哥说我复现、排查思路和操作的熟练度可以来这里上班了 🤣,Apple 的用户真的是自适应的。

再加上之前刚有一个电脑被家里另一只小猫饭饭咬坏了屏幕,决定斥巨资给我的 MBP14 补买一个 Apple Care,刚好 7.3 过一年的保,Apple 小哥跟我说一年内补买可以在这个基础上再续三年,感觉很划算,等于多了一年!

招聘

顺便发一个我司的招聘:Work With RSS3/Job Description

目前在招 DevOps Engineer/AI Engineer/Blockchain Engineer,远程办公,工作氛围很好,有疑问可以随时问我,期待未来做同事。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。

书籍

  • 索拉里斯星,与三体的设定类似,索拉里斯星围绕着双星旋转,但是不同于三体的降临或是拯救,索拉里斯星其实或许根本并不关心地球和上面渺小的人类,只是人类单向的自我中心罢了,甚至想用自己更为“高尚”的思想与价值观去改变它,探索也不过只是伪善。。
  • Normal People,很喜欢这个英剧,这两天看其他书的时候突然想到了这本,打算补一下原著。
  • What My Bones Know,去年看了一小半,这两天想到关于家庭和心理疗愈的问题,就睡前又翻了几页。
  • 阿特拉斯耸耸肩,读者送的,开始读了。

收藏

文章

视频

周报 #61 - 好朋友的婚礼与对婚姻的思考

《Photograph - Ed Sheeran》

前言

weekly_review_20240616

本篇是对 2024-06-072024-06-16 这周生活的记录与思考。

好朋友的婚礼

端午回北京参加了一场婚礼,是高中的挚友渐仔。

高中是在文科班,仅有八个男生,其中还有一位在高二时突然思想觉醒要振兴中华文坛而休学写书去了,所以陪伴着度过高三生活的只有七位了。或许是因为人很少,反倒有了些抱团取暖的相惜,毕业后直到疫情爆发都基本保持着一年两三聚的频率。

其中又有包括我在内的三位更为同频而保持着尤其亲近的联系,有小群日常闲谈、会趁着出差在北京、上海或是杭州赶着约上一顿饭,也都去各自的家中做客,互尝过厨艺,见过对彼此重要的人。

去年三人小组的另一位率先结了婚,当时的我因一头蓝色长发而有些“不过关”,没当成伴郎,其实一直还有些小遗憾。渐仔婚礼日子定下来之后就早早邀请了我当伴郎,且是唯一一个,伴郎的英文是 best man,很诱人的 title,惊喜而珍惜。

其实除去那些职责性的婚礼现场要做的事外,我觉得邀请重要的人来见证自己人生的一个重要节点本就是一件浪漫的事。

提前几天去试了一下午西装,发现气质完全 hold 不住,最后还是在常买的男装网店东拼西凑了一套休闲西服,算是穿上了这辈子最正式的一套装扮,头发没舍得剪短却也修整了下,也梳成了大人模样。

是草坪婚礼的形式,在电影里看过很多次,现实中却是第一次参加,很有仪式感却也不失温馨,早早参与到婚礼筹备过程中的我才更加能感受到这完美的仪式背后的细节与心意。

新娘那一侧的伴娘是个 E 人,E 得耀眼夺目,而我临上场了还在低头默背呈递婚戒时的左右手顺序,I 得格格不入,也算是一种有趣的反差,还有点期待看到后面的现场成片的。

婚礼与婚姻

其实早在五月中,就陪同他们去跟婚庆策划公司谈过细节,看着冗长而细致的流程表、物品单和布置图,有些惊叹于一场婚礼的复杂和昂贵程度。当时谈报价时看到两扇花门和座位上一些点缀的花束加起来逾五万,以至于我和学姐到了婚礼现场看到花门都不自觉想到这些数字。

婚礼似乎总是被冠以“一生一次”的标签,所以似乎为了这一瞬的完美哪怕付出再多心血或是花费再多金钱都值得。但我常常也在想,当一件原本感性而浪漫的事变成了 Excel 表格中下拉不完的条目和背后精确的数字,当新郎新娘的一举一动都要被完美规定时,这场婚礼究竟是为了谁而办的?

或许因为我和学姐是重体验多过形式的人,比起一场婚宴的奢华,我们或许觉得共同策划和拍摄一个关于婚姻与爱情的纪录片、一次带着头纱和祝福见双方重要却多年未见的好友的“巡回”之旅,或是在喜欢的国家城市教堂拍下一些属于两个人更真实而珍贵的承诺会更有记忆。

但站在新郎身边见证婚礼上的誓言和感动的那一刻,觉得或许怎样都好,只要是对的人。

其他

博客评论

ququ_comments

当发现从最开始用 RSS 阅读器的时代就躺在我订阅列表里的屈屈大佬也看我的周报并且还评论了时,有种追星成功 & 次元壁破了的感觉 😭

读者的陪伴

atlas_book

我生日的时候发起了一项抽奖,抽了六位留言的读者,中奖者三位选了 EpubKit 会员,两位选择了实体书,还有一位选择了微信读书。

有趣的是其中一位中奖的朋友还反向给我寄了一套大部头,去年他在我的那篇「推石头的人」的生日总结文章评论说不如让西西弗斯也耸耸肩,今天看到他给我寄来的《阿特拉斯耸耸肩》让我感受到一种奇妙而又温暖的陪伴与链接 🥰。

更换笔记系统

change_to_obsidian

今天整理了一下午笔记,发现 Logseq 某种程度上改变了我的思维习惯,虽然以 Daily Notes 的方式确实是减轻了记录的心智负担,但也让自己并不那么连续思考了,思路都转换成了一个个 bullet points,却又常常连不成一篇完整的博文,学过的很多东西慢慢也就淡忘了。

于是下定决心转到了 Obsidian,没装什么插件,想到有什么要记录的就以 「20240615 + 关键词」这种模式开头的文件 + 每篇文稿前注明 tag 这种更原始的单文本模式来记录,反倒是能够更加体系地整理一些东西。

更换 macOS 主题

dark_desktop

发现一个纯暗黑的 icon + 壁纸全套主题,效果很沉浸(除了 Finder 改不了图标很扎眼),实践效果如图。

有趣的事与物

输入

虽然大部分有意思的输入会在 「Yu’s Life」 Telegram 频道里自动同步,不过还是挑选一部分在这里列举一下,感觉更像一个 newsletter 了。

书籍

  • 虫子旁,去完游学营后开始好奇,里面讲的虫子似乎也都更亲切了些。
  • 阿特拉斯耸耸肩,读者送的,每天早起读一点。

收藏

文章

视频

❌