在云开发机上运行uvicorn的问题 |
2023-12-11 |
今天在使用uvicorn运行fastapi的app时,遇到了几个问题:
无法在code server上正常访问
由于我的开发环境在云上,用的code server,并非是本地,因此默认命令uvicorn main:app --reload
是无法正常访问的,因为code server代理的网址是https://example.com/proxy/8000
因此需要更改root-path才可以正常访问:
uvicorn main:app --root-path https://example.com/proxy/8000 --reload
对于python的自定义包无法正常载入解析
在我的main.py
中,导入自定义包:from myapp.utils.database import Database
但在myapp
文件夹下执行uvicorn main:app
时,会出现无法找到myapp
模块的错误,因此需要返回上一级文件夹,然后执行uvicorn myapp.main:app
,这样就可以了
reload监控文件夹设置
由于uvicorn在启用reload时,默认是监控当前文件夹的变动,但如果使用了uvicorn myapp.main:app
,则需要指定监控的文件:
uvicorn myapp.main:app --reload --reload-dir /path/to/myapp/
综上,全部命令为:
uvicorn myapp.main:app --reload --root-path https://example.com/proxy/8000 --reload-dir /path/to/myapp/
博客搬家到Listed-to |
2023-12-10 |
这次搬家主要是因为我的笔记应用从Obsidian(下称ob)搬到了Standard Notes(下称sn)。
我用ob也有一年多了,一直是开了sync和publish服务,但ob有很多操作一直习惯不来,比如左栏视图切换,总要想一下才能反应过来,还有就是鸡肋的搜索和没有web端,但让我下定决心搬家的原因是插件,正所谓成也插件败也插件,原先想自己做一个插件,深入了解后发现,插件的权限非常大,读取任意笔记不说,甚至可以在没有通知的情况下删除笔记……这顿时让我脊背发凉。
所以趁着黑五sn全场5折,一年只要49美金,还有免费的listed博客发布平台,比ob的sync + publish = 192美金要划算很多,而且sn不仅端到端加密,还本地加密,还有自动邮件和本地备份,操作和印象笔记也差不多,之前因为价格太贵一直没入手,所以这次就抓紧上车了。
下面简单介绍下Listed的设置,以备不时之需
关于博客数量
可以开无数个Listed,不过默认的listed.to域名国内被墙,需要绑定域名才可以在国内访问
自定义日期或者设置唯一的URL(doc):
---
date: 2017-11-20 17:08:05
canonical: [mysite.com/blog/1/po...](https://mysite.com/blog/1/post-im-importing)
---
Your story...
可用元数据字段列表:
created_at 博文创建时间
canonical 该帖子的规范 URL,供搜索引擎使用。
custom_path 覆盖帖子的默认路径。如果是从其他博客迁移过来,这很有用。(例如: my-blog-post )
desc 本帖的自定义元描述,供搜索引擎使用。
hidden true/false. 是否应从作者简介中隐藏文章(但仍可通过 URL 访问)
image_url 社交媒体网站在链接预览卡中使用的图片。
metatype [css, html, json]. 用于创建自定义主题。
page true/false. 用于在作者标题中创建专用链接。
page_link 如果 page 为 true,且设置了该值,页面将作为外部 URL 打开。
page_sort 一个数字。数字越小,页面链接出现在作者页眉的时间就越早。
关于自定义CSS
先根据官方文档创建css文件
如果想做成twitter类型,不显示正文,只显示标题:
---
metatype: css
---
.author-post .post-body {
display: none;
}
我博客在用的css:gist.github.com/versun/38…
关于Newsletter
默认开通newsletter,所有邮件都是从[email protected]发出的,而且为了隐私安全,博主是无法看到订阅人邮箱的,只能知道人数。
所以以后如果转平台,是无法批量导出订阅人的,只能发邮件让订阅者重新在新平台订阅。
关于图片
虽然Standard Notes笔记里可以添加图片,但发布到Listed后并不会显示,因此需要自行使用图床,稍微麻烦了些
解决macOS下OneDrive的同步问题 |
2023-11-21 |
我的OneDrive下有4.7T的资料,需要全部同步下载到macOS下的外置硬盘,期间遇到了无数的问题,同步了数次才成功,因此在这里记录下主要的问题和相关的解决方案。
安装Onedrive
一定要去官网下载OneDrive,不要在Appstore里安装。
同步
初次开启OneDrive或者推出OneDrive后,如果文件数量超多,则会一直卡在“正在处理”的状态,这时不要退出,等待处理完成后就会开始下载。
建议一次一个大文件夹,不要一下子全部同步,不方便后续的核对
下载的文件
下载的文件并不在Finder左边的OneDrive文件夹里,该文件夹里都是链接文件,并非真实的文件。
真实文件都在隐藏文件夹 “.ODContainer-OneDrive” 下
比对文件大小
OneDrive官网不会显示文件夹的大小,需要进入OneDrive软件的设置里,点击“管理存储空间”可以查看
mac的对于文件大小的计算方式和微软不同,所以下载的文件大小会大于网页上显示的大小 需要在隐藏文件夹 “.ODContainer-OneDrive” 下,才可以查看文件大小 对于超大文件夹(大于2T),mac下右键文件夹详情里的文件大小有时不准确,需要进入文件夹比对子文件的大小
无法同步
一般情况下,重启软件或电脑是可以解决的
但如果软件有红色提示 存在同步问题的文件,则需要在网页上下载有问题的文件后,在网页端删除该文件。
这样软件就不会提示了,就会继续同步
macOS的Python环境配置 |
2023-11-18 |
警告:千万不要使用macOS默认安装的python。。。。
最佳配置是使用pyenv,因为它可以控制shell路径,可以配置全局默认版本
安装pyenv
Github仓库
官方安装指南
这边只建议使用Homebrew来安装,可以省很多麻烦
首先需要安装依赖 brew install openssl readline sqlite3 xz zlib tcl-tk
然后再pyenvbrew install pyenv
安装Python
可先运行pyenv install --list
查看所有可安装的版本
pyenv install 3.12.0
设置全局默认
`pyenv global 3.12.0
设置默认环境
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
重启终端就可以自动生效了
使用PDM来管理虚拟环境
Github仓库 | 官方文档
安装brew install pdm
初始化一个新的 PDM 项目: pdm init
(可选) 选择python版本号 pdm use 3.11
安装包:pdm add django
添加依赖: pdm add requests django
树莓派4安装vscode并开启tunnel |
2023-08-28 |
如果你的树莓派可以外网访问,或者只想在内网使用vscode server,则建议直接使用Remove SSH会好些。
但如果无法外网访问,除了设置DDNS外,还可以使用tunnel,还可以网页访问vscode,很方便
参考:https://code.visualstudio.com/docs/remote/tunnels
如果你的树莓派是Raspberry Pi OS,则直接运行下面的代码安装即可:
sudo apt update
sudo apt install code
如果是debian或者其它第三方的系统,则运行下面的代码安装:
ref:https://code.visualstudio.com/docs/setup/linux
sudo apt-get install wget gpg
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list'
rm -f packages.microsoft.gpg
sudo apt install apt-transport-https
sudo apt update
sudo apt install code # or code-insiders
接着,下载CLI工具:https://code.visualstudio.com/download
选择Linux下的Arm64版本的CLI
解压后放到/usr/local/bin下
开启断开连接后服务保持功能
code tunnel service install
sudo loginctl enable-linger $USER
查看日志的命令: code tunnel service log
关闭服务保持功能: code tunnel service uninstall
开启Tunnel
code tunnel
需确保树莓派的网络能正常访问Github
后续按照提示完成认证即可
客户端配置
客户端的vscode上,安装Remote – Tunnel插件后,点击左下方的绿色按钮,选择Connect to Tunnel,通过Github认证后,你的树莓派名称就会显示,点击即可连接使用。
Web版:https://vscode.dev/tunnel/你设置的名称
NAS惊险记 |
2023-08-21 |
这周我的威联通NAS因为一次意外断电,发生了硬盘坏块,数据丢失的情况,好在之前做好了备份策略,数据无损恢复,只是浪费了些时间。
这次事件发生了很多之前完全想不到的情况 ps:人类果然无法逃脱熵增定律
在此分享下事件过程:
我的备份策略:
首先我不相信任何的软raid方案,因此我的NAS设置为raid 0,寻求最佳性能
所有文件自动备份在NAS上,并实时同步到OneDrive
个人文档和重要文件也会同步到iCloud上
NAS连接外置硬盘,定时备份重要文件
目的: 通过不同的云服务商来确保数据安全,同时确保重要文件能最快速度的恢复并能临时使用
在发生意外断电后,在检查UPS电量和电源连接情况后,重启NAS,系统提示发生意外断电,需检查磁盘,运行了一天,果然有坏块,数据丢失。
由于日常使用的文件,均在iCloud上,所以不受影响
NAS重新绑定OneDrive时,再次出现问题,由于太过信任微软的Authenticator应用,使用的e5子账户可能因为长期没有登录,应用死活收不到验证码
好在电脑上的onedrive会话还在有效期,赶紧连接nas并全部下载下来,然后新建e5账户,并开启双因子和短信验证。
NAS绑定新的OneDrive账户,开始同步
至此,数据已全部找回,并在事件发生期间没有影响到日常的使用。
教训:
1.做好nas的物理隔离
2.所有账户的登录验证方式至少激活2种以上
3.对于非重要的冷数据,有必要再找个云服务商,不能只靠onedrive,目前在考虑BorgBase服务
小插曲:在意外发生时,我还在上班,由于正好要查看一个冷数据,之前都是VPN连接到内网的NAS上查看,但这次只能使用onedrive,好在app会话有效期还在。
但在我下载后准备使用Cryptomator解密vault时,才发现这个app竟然开始收费了。。。。好在有30天的试用期,看来要重新考虑加密方案了。
2023–12–01 更新
由于远程访问文件的需求较低,因此把NAS卖了,换了硬盘柜,并使用BackBlaze的Computer Backup备份,热文件依旧使用iCloud备份
如何自建Newsletter服务 |
2023-07-12 |
由于我原来的54321周刊部署在Substack平台, 但该平台国内访问不了, 而且发送的邮件附加了点击跟踪, 导致所有链接都需要从Substack服务器进行跳转, 没有科学上网的话根本访问不了, 体验很差, 所以有必要从Substack搬出来了.
TLDR: 主页: 以Github为主, 类似阮一峰的科技周刊, 可以在cloudflare部署静态网页 RSS: 将内容发布到Github Release, 会有自动生成的RSS, 只要在release网址最后加.atom 邮件服务: 在Pikapods部署Listmonk, 并使用AWS SES服务, 非常便宜
正文:
使用Github Release发布
我的周刊从一开始就同步上传到Github上, 所以这次主要是解决Github Release的设置. 从原来的直接上传到docs文件夹下改为使用Github Release来发布, 体验更好,而且release的标签可以作为id进行短网址跳转(后面会设置): 访问 54321.versun.me/p/29 自动跳转到 github.com/versun/54321-Weekly/releases/tag/29
同时, 我设置了一个Github Action, 可以在每次Releases新的内容后, 自动将内容保存为md文件并push到docs文件下: 在库的根目录下创建 .github/workflows/create-release-note.yml
name: Create Release Note
on:
workflow_dispatch:
release:
types: [published]
jobs:
create-release-note:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
ref: main
- name: Create release note
run: |
echo # ${{ github.event.release.name }} > docs/${{ github.event.release.tag_name }}.md
echo ${{ github.event.release.body }} >> docs/${{ github.event.release.tag_name }}.md
- name: Commit
uses: EndBug/add-and-commit@v9
with:
message: Release ${{ github.event.release.tag_name }}
add: docs/*.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
push到github上后就可以了, 每次有新的release发布,就会自动运行,保存内容到docs文件夹下(需先创建好docs文件夹)
设置静态页面
本人比较懒, 不想折腾Jekyll等工具, 所以直接使用Readme.md做为主页, 部署到Cloudflare上, 确保国内能访问, 这次使用worker而不用pages, 步骤如下:
在Workers & Pages新建一个application -> worker 先不添加代码, 直接部署, 然后点击刚建的worker, 选择Quick edit, 修改并粘贴下面的代码
async function handleRequest(request) {
const url = new URL(request.url)
const path = url.pathname
const user = 'versun' //Github用户名
const repo = '54321-Weekly' //仓库名
if (!user || !repo) {
return new Response('Invalid URL format.')
}
try {
const response = await fetch(`[raw.githubusercontent.com/$](https://raw.githubusercontent.com/$){user}/${repo}/main/README.md`)
const text = await response.text()
const markdown = await renderMarkdown(text)
const modifiedHtml = addSubscriptionForm(markdown)
return new Response(modifiedHtml, {
headers: {
'Content-Type': 'text/html; charset=utf-8',
'Cache-Control': 'public, max-age=3600'
}
})
} catch (error) {
return new Response(`Error fetching README.md for ${user}/${repo}: ${error}`, { status: 500 })
}
}
//处理markdown内容
async function renderMarkdown(markdown) {
const response = await fetch('[api.github.com/markdown'...](https://api.github.com/markdown',) {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': '54321-Weekly' //随便写
},
body: JSON.stringify({
text: markdown,
mode: 'gfm',
context: 'gollum/gollum'
})
})
const html = await response.text()
return html
}
addEventListener('fetch', event => {
const url = new URL(event.request.url)
//设置跳转,54321.versun.me/feed 跳转到 repo release的rss
if (url.hostname === '54321.versun.me') {
if (url.pathname.startsWith('/feed')) {
event.respondWith(Response.redirect('[github.com/versun/54...](https://github.com/versun/54321-Weekly/releases.atom',) 301))
return
}
// 54321.versun.me/p/number 跳转到 repo release的tag上
if (url.pathname.startsWith('/p/')) {
const tag = url.pathname.split('/p/')[1]
event.respondWith(Response.redirect(`[github.com/versun/54...](https://github.com/versun/54321-Weekly/releases/tag/$){tag}`, 301))
return
}
}
event.respondWith(handleRequest(event.request))
})
保存部署后, 点击Triggers, 添加自定义域名
部署Newsletter管理后台Listmonk
不熟悉Listmonk的, 可以去官网了解下, 开源免费, 很好用, 也提供了Newsletter的landing page和rss, 但2.4版本文章的url没法自定义, 全都是很长的uuid格式, rss无法全文输出, 所以这次不做考虑, 可以在后台关掉. 可以使用Railway或者PikaPods一键部署, 我选择PikaPods, 很方便, 一个月只要1.4美金即可. 具体listmonk设置可以参考官方文档, 没什么难度
申请开通AWS SES API
在创建AWS账户后, 可以开通SES服务, 但刚开通只会给你sandbox测试的权限, 还需要申请product权限. 申请方法很简单, 在ses管理后台首页, 它会提示你让你申请, 点击进去后, 用因为表面你的理由, 注意: 一定要说明每月每日的发送量是多少, 然后为什么需要该服务, 再加上你的网址就可以了, 可以参考下面的:
I am writing to apply for AWS SES services to help me with my weekly newsletter. Currently, I have around 50 subscribers, and my monthly email volume is less than 500.
My blog: notes.versun.me
My Newsletter: 54321.versun.me
I believe that AWS SES would be the perfect solution for my needs, as it provides a reliable and cost-effective way to send emails to my subscribers.
I am impressed by the features that AWS SES offers, such as its ability to track email deliverability and provide detailed analytics.
Thank you for your time and consideration. I look forward to hearing back from you soon.
24小时左右就能通过了. 通过后再SES后台, 点击SMTP settings 有我们需要的SMTP endpoint url, 添加到listmonk后台, 然后点击Create SMTP credentials, 生成用户名和密码, 同样添加到listmonk后台,选择login模式即可
以上就是全部流程啦.
Github-Sponsorkit使用说明 |
2023-05-13 |
第一步:在需要添加sponsor模块的repo根目录下新建文件sponsorkit.config.js
该文件会自动输出svg,png和json格式的sponsor信息
import { defineConfig, presets } from 'sponsorkit'
export default defineConfig({
// Rendering configs
width: 800,
formats: ['svg', 'png','json'],
tiers: [
// Past sponsors, currently only supports GitHub
{
title: 'Past Sponsors',
monthlyDollars: -1,
preset: presets.xs,
},
// Default tier
{
title: 'Backers',
preset: presets.base,
},
{
title: 'Sponsors',
monthlyDollars: 0.5,
preset: presets.medium,
},
{
title: 'Silver Sponsors',
monthlyDollars: 1,
preset: presets.large,
},
{
title: 'Gold Sponsors',
monthlyDollars: 5,
preset: presets.xl,
},
],
})
第二步:目录添加package.json文件
{
"type": "module",
"packageManager": "[email protected]",
"scripts": {
"build": "sponsorkit"
},
"devDependencies": {
"@types/node": "^20.12.11",
"sponsorkit": "^0.14.0"
}
}
第三步:获取token
SPONSORKIT_GITHUB_TOKEN在头像->Settings->Developer settings->Personal->Tokens添加,需要有read:user
and read:org
权限
其它Token的获取地址请参考这里
第四步:添加Token
打开repo -> Settings -> Secrets and variables -> Actions, 点击New repository secret
添加你需要的token:

第五步:添加Github action
也就是在.github/workflows文件夹下新建scheduler.yml文件
name: Scheduler
on:
workflow_dispatch:
schedule:
- cron: '30 5,17 * * *'
push:
branches: [main]
jobs:
update-sponsors:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
- name: Set node
uses: actions/setup-node@v4
with:
node-version: lts/*
- run: corepack enable && pnpm i
- name: Update sponsors
run: pnpm exec sponsorkit --dir .
env:
SPONSORKIT_GITHUB_LOGIN: versun
SPONSORKIT_GITHUB_TOKEN: ${{ secrets.SPONSORKIT_GITHUB_TOKEN }}
SPONSORKIT_AFDIAN_USER_ID: ${{ secrets.SPONSORKIT_AFDIAN_USER_ID }}
SPONSORKIT_AFDIAN_TOKEN: ${{ secrets.SPONSORKIT_AFDIAN_TOKEN }}
SPONSORKIT_OPENCOLLECTIVE_KEY: ${{ secrets.SPONSORKIT_OPENCOLLECTIVE_KEY }}
SPONSORKIT_OPENCOLLECTIVE_SLUG: ${{ secrets.SPONSORKIT_OPENCOLLECTIVE_SLUG }}
SPONSORKIT_OPENCOLLECTIVE_TYPE: collective
SPONSORKIT_POLAR_TOKEN: ${{ secrets.SPONSORKIT_POLAR_TOKEN }}
- name: Commit
uses: EndBug/add-and-commit@v5
with:
message: 'chore: update sponsors.svg'
add: 'sponsors.*'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
最后,授予Action写权限:
打开Repo -> Settings -> Actions -> General
在最后的Workflow permissions勾选“Read and write permissions”即可。
完成,你现在可以去Actions运行workflow,正常情况下会把输出的svg等文件提交到根目录的sponsorkit文件夹下
Pinboard_in快速上手 |
2023-05-13 |
==Pinboard功能==
- 书签管理
- 稍后阅读
- 同步 Pocket, Twitter, Instapaper
- 浏览器标签页保存
- 简易note
- RSS, 插件
- 书签存档服务
==隐私设置==
Pinboard默认书签是公开的,如果您要私人使用,建议您打开隐私模式后再导入书签:
settings -> privacy -> Turn Privacy Lock On
打开后,名字旁边会有个


==导入导出书签==
导入: 使用浏览器导出的html文件来导入: settings -> import
通过邮箱导入: 首先启用该功能(勾选最后的Email设置), 将会显示专属的邮件地址, 邮件格式如下:
主题: 书签的标题
内容:第一行为网址,第二行为描述,第三行为标签
导出: export
==添加插件==
查看Pinboard Resources, 选择您要添加的插件或应用
如果你要添加书签栏的插件,查看howto
==书签管理==
Pinboard只有2种管理方式: Tags和Bundles
标签Tags
每个链接可以添加多个标签(tags1,tags2)
集合Bundles
整合多个标签,类似标签文件夹(bundles1:tags1,bundles1:tags2)
需先在settings中打开bundles功能
打开后,点击首页的no tag bundles

然后再点击new bundle
在Create Tag Bundle页面,左边为所有的tag,右边为需添加到bundle的tag

点击左边需要添加的tag(可多个),然后点击中间的转换按钮,选中的tag将会显示在右边栏中
最后输入上方的bundle name,点击保存即可将所选择的tag加到对应的bundle下

Tips:
- 可双击tag快速转换左右列表
- bundle暂时无法在添加书签时指定,只能手动
- 不能嵌套bundle
==RSS订阅==
可用RSS订阅自己/某人的pinboard页面变化,具体查看这里
==浏览器标签页保存==
该功能需要安装浏览器插件才能使用

点击后会跳出新页面,选择需要保存的tab,输入Name后点保存即可

保存后,即可在首页的tabs里面看到


==同步Twitter==
在settings里面绑定twitter账户,最多3个

之后即可在首页查看自己发的twitter和喜欢的twitter

点击favs可查看喜欢的推

主要功能就是这些,其它可在how-to 上查看
UX-Learning-Path |
2023-05-13 |
Codecademy Courses Path
- Introduction to UI and UX Design
- Learn User Research: Generative
- Learn Design Thinking: Ideation
- Learn Interaction Design
- Create a Professional Website with Velo by Wix | Codecademy
Designlab Courses Path
UX Academy: Learn UX UI Design | Designlab
1 Design Is…
Begin your learning journey by gaining essential information about the field of UX and UI design.
Determine what design means to you and set achievable goals for yourself.
17 Lessons / 5 Projects
2 User Research
Get started on a realistic design project by practicing various research methods such as interviewing actual human beings.
Synthesize your research into actionable insights.
21 Lessons / 14 Projects
3 Ideation to Prioritization
Learn how to think divergently using numerous brainstorming techniques before deciding on a product idea that would bring value to the people you interviewed.
10 Lessons / 8 Projects
4 Information Architecture
Build up your skills in organizing information, content strategy, navigational design, search engine optimization, and sitemap diagramming, all of which contribute to your project.
13 Lessons / 6 Projects
5 Interaction Design
Develop task flows, user flows, and learn the fundamentals of usability, accessibility, and inclusion.
Then, take a mobile-first approach to creating responsive wireframes.
29 Lessons / 12 Projects
6 User Interface Design
Apply visual design principles to the creation of components that will be utilized in your prototype.
Learn the basics of branding, typography, color theory, and iconography.
22 Lessons / 8 Projects
7 Prototyping and Testing
Prepare a high-fidelity prototype that you will then test and iterate upon.
Wrap up your first major design project by preparing your designs for hand-off to software developers.
16 Lessons / 10 Projects
8 Personal Brand and Portfolio Setup
Register a domain name for your portfolio
Create a first draft of your portfolio site
Capstone Project 1: Responsive Web Design
Design a website with mobile, tablet, and desktop breakpoints
Showcase your ability to use layout grids and design for multiple devices
Capstone Project 2: Add a Feature to an Existing Product
Design a new feature for an existing digital product
Demonstrate how you can work within brand guidelines and integrate
with existing feature
Capstone Project 3: End-to-End Application
Design an iOS or Android mobile app experience from scratch
Show off your skills as a generalist UX designer, from research to handoff
UX Academy Graduation
Add the Capstone projects to your portfolio
Submit your portfolio to our expert panel for review
