ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

又一 VSCode 神器诞生!用 Foam 把 Markdown 笔记发布到 GitHub Pages

又一 VSCode 神器诞生!用 Foam 把 Markdown 笔记发布到 GitHub Pages 1. 为什么我放弃了传统笔记软件转投 VSCode Foam 的 Markdown 知识库如果你和我一样平时写技术笔记、整理项目文档、甚至维护个人博客大概率经历过这样的循环一开始用某款笔记软件写着写着发现导出格式锁死想迁移到静态站点生成器时图片路径、双链引用全乱套。更别提有些工具把数据存在私有格式里哪天服务停了几年的积累直接归零。Foam 解决的就是这个痛点。它本质上是一套跑在 VSCode 里的 Markdown 知识管理扩展核心能力有三个第一用[[wikilink]]语法做双向链接自动生成关系图谱第二所有内容都是纯 Markdown 文件存在你本地文件夹里随时可以用 Git 管理第三配合 GitHub Actions能把整个笔记库直接发布成 GitHub Pages 静态站点。适合谁用我觉得三类人最合适一是长期写技术博客但不想被平台绑定的开发者二是需要维护内部知识库、又希望用 Git 做版本控制的团队三是已经在 VSCode 里写代码不想再开一个笔记软件来回切换的人。我试过把之前散落在各处的两百多篇笔记迁移过来整个过程比想象中顺。下面我把从零搭建到发布上线的完整流程拆开讲包括我踩过的坑和最终跑通的配置。2. Foam 环境准备与 TaoToken 模型接入前置配置在开始之前你需要先确认本地环境。VSCode 版本建议 1.80 以上Node.js 装 18 LTS 或更高。Foam 本身是一个 VSCode 扩展直接在扩展市场搜索 Foam 安装即可作者是 Foam 团队。但这里有个容易被忽略的点很多人在配置 Foam 的模板和自动化脚本时会用到 AI 辅助生成文档摘要、自动补全双链建议或者用脚本批量处理 Markdown 元数据。这时候如果本地没有稳定的模型调用通道脚本跑一半报错会很影响效率。我的做法是提前把模型调用层配好。TaoToken 提供了一套兼容 OpenAI 接口规范的 APIBase URL 是https://taotoken.net/api你可以在 Foam 项目的脚本里直接调用。具体来说如果你要用 Node.js 写一个自动生成笔记摘要的脚本可以这样初始化// scripts/summarize.js const OpenAI require(openai); const client new OpenAI({ apiKey: process.env.TAOTOKEN_API_KEY, baseURL: https://taotoken.net/api }); async function summarizeNote(content) { const completion await client.chat.completions.create({ model: gpt-4o-mini, messages: [ { role: system, content: 你是一个技术笔记摘要助手用一句话概括以下内容。 }, { role: user, content: content } ] }); return completion.choices[0].message.content; } module.exports { summarizeNote };API Key 的获取路径是登录 TaoToken 控制台在 API Keys 页面创建。建议把 Key 写到项目根目录的.env文件里然后加进.gitignore避免推到 GitHub 上泄露。# .env TAOTOKEN_API_KEYsk-你的实际key如果你更习惯用命令行工具做批量处理TaoToken 也支持标准的 OpenAI SDK 调用方式。比如用 curl 测试连通性curl https://taotoken.net/api/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -d { model: gpt-4o-mini, messages: [{role: user, content: 用一句话解释什么是双向链接}] }返回正常的话你会看到choices数组里有内容。这一步确认通了后面 Foam 的自动化脚本才能稳定跑。另外Foam 的工作区配置建议在.vscode/settings.json里加上这些避免 Markdown 链接跳转失效{ foam.files.ignore: [ **/.git/**, **/node_modules/**, **/_site/** ], foam.edit.linkReferenceDefinitions: withExtensions, editor.quickSuggestions: { other: true, comments: false, strings: true } }linkReferenceDefinitions设为withExtensions是为了让 Foam 生成的链接带.md后缀这样在 GitHub Pages 上部署时路径解析更稳定。这个细节我调了两次才确认默认配置在本地预览没问题但推到 Pages 上会出现 404。3. 可复制的 Foam 配置片段与 GitHub Actions 部署文件Foam 初始化后项目根目录会生成一个.foam文件夹和若干模板文件。但默认的 GitHub Pages 部署流程需要自己补。我把我实际跑通的配置完整贴出来你可以直接复制。首先是 Foam 的工作区配置文件foam.json放在项目根目录{ version: 1.0.0, workspace: { root: ., notesDir: notes, assetsDir: assets, templatesDir: .foam/templates }, publish: { outputDir: _site, baseUrl: /your-repo-name, exclude: [_site, .git, node_modules, .foam] } }注意baseUrl要改成你 GitHub 仓库的名字比如仓库叫my-notes就写/my-notes。这个配置决定了静态站点里所有链接的前缀写错了会出现样式丢失或跳转 404。接下来是 GitHub Actions 的部署文件路径是.github/workflows/deploy.ymlname: Deploy Foam to GitHub Pages on: push: branches: [main] workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: pages cancel-in-progress: false jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkoutv4 - name: Setup Node uses: actions/setup-nodev4 with: node-version: 18 - name: Install dependencies run: | npm install -g foam-cli npm install - name: Build Foam site run: | foam build --output _site - name: Upload artifact uses: actions/upload-pages-artifactv3 with: path: _site deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pagesv4这里有个关键点foam build命令需要foam-cli全局安装但 Foam 的 VSCode 扩展和 CLI 是两套东西。CLI 负责把 Markdown 编译成静态 HTML扩展负责编辑体验。我一开始只装了扩展Actions 跑起来报foam: command not found后来在 workflow 里加了npm install -g foam-cli才解决。另外如果你的笔记里有图片建议统一放在assets文件夹引用时用相对路径![描述](../assets/image.png)。Foam 构建时会自动处理这些资源路径但前提是foam.json里的assetsDir配置正确。本地预览命令也很简单在项目根目录执行foam build --output _site --serve它会启动一个本地服务器默认端口 3000浏览器打开http://localhost:3000就能看到和线上一致的渲染效果。我习惯在推送到 GitHub 之前先本地跑一遍确认双链跳转和图片显示都正常。4. 验证请求与成功结果从双链笔记到静态站点的完整演示配置写完后最关键的一步是验证整条链路是否跑通。我拿一个实际场景来演示创建两篇互相引用的笔记然后构建、部署、访问。第一步在notes文件夹下新建ai-workflow.md# AI 辅助工作流 我平时用 [[taotoken-api]] 来做模型调用配合 [[foam-publish]] 把笔记发布上线。 ## 常用命令 - 本地预览foam build --serve - 构建静态文件foam build --output _site再新建taotoken-api.md# TaoToken API 接入 Base URL 是 https://taotoken.net/api兼容 OpenAI 接口规范。 相关笔记[[ai-workflow]]保存后Foam 会自动在右侧面板生成关系图谱你能看到两个节点之间有连线。这就是双向链接的可视化效果。第二步本地构建。执行foam build --output _site终端会输出类似这样的日志[info] Loading workspace from /path/to/your-notes [info] Found 2 notes [info] Resolving links... [info] Generated _site/index.html [info] Generated _site/ai-workflow.html [info] Generated _site/taotoken-api.html [info] Build complete in 1.2s如果看到Build complete说明 Markdown 到 HTML 的转换没问题。打开_site/ai-workflow.html检查里面的链接是否指向taotoken-api.html图片路径是否正确。第三步推送到 GitHub。先确认仓库的 Pages 设置里Source 选的是 GitHub Actions。然后git add . git commit -m feat: add foam notes and deploy workflow git push origin main推送后Actions 会自动触发。你可以在仓库的 Actions 标签页看到Deploy Foam to GitHub Pages的工作流在跑。等它变成绿色勾访问https://你的用户名.github.io/仓库名/就能看到笔记站点了。我实测下来从 push 到 Pages 更新大概需要 40 秒到 1 分钟。如果超过两分钟还没生效先去 Actions 日志里看 build 步骤有没有报错。第四步验证线上双链跳转。在线上页面点击[[taotoken-api]]对应的链接应该能正常跳到taotoken-api.html。如果跳转后是 404大概率是foam.json里的baseUrl没配对或者链接生成时没带.html后缀。这里补充一个我踩过的坑Foam 默认生成的链接是[[taotoken-api]]这种 wikilink 格式构建时会转成a hreftaotoken-api.html。但如果你在 Markdown 里手写了[链接](taotoken-api)这种不带后缀的构建后可能变成taotoken-api而不是taotoken-api.html在 Pages 上就会 404。解决办法是统一用 wikilink 语法或者手写链接时带上.html。5. 本篇常见错误排查401、local proxy failed、reading choices 与 OAuth 报错这一节我把实际遇到过的报错和排查过程整理出来你如果卡住了可以对照看。401 Unauthorized这个最常见通常出现在调用 TaoToken API 的脚本里。报错信息类似Error: 401 Unauthorized { error: { message: Invalid API key provided, type: invalid_request_error } }排查步骤第一确认.env文件里的TAOTOKEN_API_KEY没有多余空格或换行第二确认脚本里读取环境变量的方式正确Node.js 里需要require(dotenv).config()第三去 TaoToken 控制台的 API Keys 页面确认这个 Key 还在有效期内没有被人为禁用。如果是在 GitHub Actions 里跑脚本报 401检查仓库的 Secrets 设置TAOTOKEN_API_KEY要加到 Repository secrets 里然后在 workflow 里通过${{ secrets.TAOTOKEN_API_KEY }}引用。local proxy failed这个报错一般出现在 Foam 构建阶段信息类似[error] local proxy failed: connect ECONNREFUSED 127.0.0.1:8080原因是 Foam 的某些插件或脚本尝试走本地代理但代理服务没启动。如果你没有用代理检查 VSCode 的http.proxy设置是不是被改过。在settings.json里把http.proxy: 设为空字符串或者直接删掉这一项。另外如果你在.npmrc或.env里配了HTTP_PROXY也会导致这个问题。执行npm config delete proxy和npm config delete https-proxy清理掉。reading choices这个报错通常出现在模型调用返回结果解析时TypeError: Cannot read properties of undefined (reading choices)意思是 API 返回的 JSON 里没有choices字段。可能原因有三个一是请求体格式不对比如messages数组为空二是模型名称写错了TaoToken 返回了错误信息而不是正常 completion三是网络问题导致返回了 HTML 错误页而不是 JSON。排查方法在调用处打印完整的 responseconst response await client.chat.completions.create({...}); console.log(JSON.stringify(response, null, 2));如果看到error字段根据错误信息调整。如果看到的是 HTML检查 Base URL 是不是写成了https://taotoken.net/api/带了多余斜杠正确写法是https://taotoken.net/api。OAuth 相关报错如果你在 Foam 里集成了 GitHub 相关的 OAuth 流程比如自动创建 issue 或同步 gist可能会遇到Error: OAuth token exchange failed: invalid_client这个一般是 GitHub OAuth App 的 Client ID 或 Client Secret 配错了。去 GitHub Settings - Developer settings - OAuth Apps 里核对回调地址要和你 Foam 脚本里写的一致。如果是在 Actions 里跑确保 Secrets 里的GH_CLIENT_ID和GH_CLIENT_SECRET都正确设置。还有一个容易忽略的点GitHub Pages 部署时如果仓库是私有的Pages 功能需要 GitHub Pro 或 Team 计划。免费账号只能对公开仓库开启 Pages。如果你推上去后 Actions 成功但 Pages 不更新先确认仓库可见性。6. 长期维护与扩展把 Foam 知识库接入 Coding Plan 的实践笔记库搭起来只是第一步长期用下去的关键是让它融入你的日常工作流。我现在的做法是Foam 负责本地知识沉淀TaoToken 的 Coding Plan 负责在写代码时随时调用模型做辅助两者通过 Git 仓库打通。具体来说我在 Foam 项目里加了一个scripts/文件夹放一些自动化脚本。比如每天定时把新增的笔记标题和摘要同步到一个索引文件方便快速检索// scripts/build-index.js const fs require(fs); const path require(path); const { summarizeNote } require(./summarize); const notesDir path.join(__dirname, ../notes); const outputFile path.join(__dirname, ../index.json); async function buildIndex() { const files fs.readdirSync(notesDir).filter(f f.endsWith(.md)); const index []; for (const file of files) { const content fs.readFileSync(path.join(notesDir, file), utf-8); const title content.match(/^#\s(.)$/m)?.[1] || file; const summary await summarizeNote(content.slice(0, 500)); index.push({ file, title, summary }); } fs.writeFileSync(outputFile, JSON.stringify(index, null, 2)); console.log(Indexed ${index.length} notes.); } buildIndex();这个脚本跑一次大概消耗几百个 token成本很低但生成的索引文件可以直接被 Foam 的搜索插件读取找笔记快很多。如果你需要更复杂的 Agent 能力比如让模型自动帮你整理双链关系、推荐相关笔记TaoToken 的 Coding Plan 提供了更完整的调用额度和管理界面。我目前用它来跑每周的笔记归档任务把散落的临时笔记归类到正式目录并自动生成周报摘要。接入方式还是标准的 OpenAI 兼容接口只是模型可以换成更适合长文本处理的版本。在脚本里改一行model参数就行const completion await client.chat.completions.create({ model: claude-3-5-sonnet, messages: [...] });最后说一个实用技巧Foam 的模板功能可以大幅减少重复劳动。在.foam/templates/下建一个daily-note.md# {{date:YYYY-MM-DD}} ## 今日完成 ## 遇到的问题 ## 相关笔记然后在 VSCode 命令面板里执行Foam: Create Note from Template选这个模板就会自动生成带日期的日记文件。配合 Git 的每日提交你的知识库会自然生长而不是靠意志力硬撑。整套流程跑通后我现在的状态是早上打开 VSCode写代码的同时顺手把技术决策记到 Foam 里双链自动关联晚上 push 一次GitHub Actions 自动构建部署线上站点同步更新。不需要额外打开任何笔记软件也不需要手动导出导入。如果你也想试试从安装 Foam 扩展和配好 TaoToken 的 API Key 开始就行。
返回列表