写作最消耗人的部分往往不是写,而是写完之后那一堆杂事:调格式、传图、发到不同平台、改错别字。这些事加起来能占掉一半时间。

我的解法是把整条链路压到只剩两步:写 Markdown,然后 跑一条命令。

目录结构

blog/
├── posts/
│   ├── hello-world.md
│   └── chinese-typography.md
├── assets/
└── scripts/
    └── build.js

一篇文章就是一个 .md 文件。文件名就是 URL 里的 slug,改文件名等于改链接,所以我尽量一次取好。

Frontmatter

文件开头用三条横线包一段元信息:

---
title: 用 Markdown 构建我的写作流水线
date: 2026-09-15
tags: [工具, 写作]
excerpt: 从纯文本开始,到自动发布结束。
---

只留四个字段。字段越少,写的时候越不会犹豫。

构建脚本

核心逻辑不到四十行:

import fs from "node:fs";
import path from "node:path";

const dir = "posts";
const files = fs.readdirSync(dir).filter((f) => f.endsWith(".md"));

const posts = files.map((file) => {
  const raw = fs.readFileSync(path.join(dir, file), "utf8");
  const [, front = "", body = ""] = raw.split(/^---$/m);

  const meta = Object.fromEntries(
    front
      .split("\n")
      .filter(Boolean)
      .map((line) => {
        const i = line.indexOf(":");
        return [line.slice(0, i).trim(), line.slice(i + 1).trim()];
      })
  );

  return {
    slug: file.replace(/\.md$/, ""),
    ...meta,
    content: body.trim(),
  };
});

fs.writeFileSync(
  "assets/data/posts.js",
  `window.POSTS = ${JSON.stringify(posts, null, 2)};`
);

没有依赖,没有配置,node scripts/build.js 就完事。

为什么不用现成的静态站点生成器

用过 Hugo、Hexo、Astro。它们都很好,问题是:

  • 主题定制要读它的模板语法
  • 升级大版本时配置会静默失效
  • 想加一个"阅读进度条"要翻半天文档

自己写四十行,什么都能改,改坏了也看得懂。

图片怎么办

一个约定:图片放在 web/public/img/ 下,文件名和文章 slug 一致,加序号。

![县城清晨的街道](/img/county-01.jpg)

这样找图的时候不用回忆,直接按文章名搜。

校对

错别字靠眼睛看是靠不住的。我固定用两个办法:

  1. 大声读一遍(最有效,也最羞耻)
  2. 搜索高频错词表:「的地得」「在再」「做作」「即既」

第二遍一定隔一天再看。隔一天之后你会变成一个陌生人,看自己的文章格外挑剔。

一点感想

工具的价值在于让人忘记工具。这套流程用了快两年,我几乎没再想过"怎么发文章"这件事——它退到了背景里,只剩下写。

这才是好工具该有的样子。