Skip to content

Hardream 团队的文档系统

Tip

对于普通团队成员来说,只需要简单看看“本地文档系统”和“内部文档仓库维护方案”两小节.

内部文档仓库的组织结构也遵循本地文档系统一节的设计.

对于文档系统管理员来说,需要了解全篇内容.

本地文档系统

作用和设计

  • 本地文档系统的作用: Jeek认为本地文档系统的作用在于为大脑减少记忆负担, 让大脑完全地发挥决策功能. 此外, 在整理文档的过程中, 大脑应形成知识体系.

  • 本地文档系统的设计: 随着ChatGPT, Gemini等大模型技术的发展, 人们越来越不需要留存记忆性内容了. 本地的文档系统的作用在于留存个性化的痕迹. 以下是Jeek的文档系统的设计建议:

    1. ToDo List: 在工作的时候, 人们经常会有突发的灵感或者突然需要处理的事务. 如果这些噪音一直堆积在大脑里, 会让大脑变得低效. 所以及时将需要留待之后处理的灵感或者事务记录到ToDo List中不仅可以防止遗忘, 也可以提高工作效率.
    2. Record: 日记/周记/月记/年记. 人们在工作的时候如果能够进入心流状态是令人惬意的. 但是可能会导致人们失去对于全局决策的视野. 适时进行记录并不是一种监督, 而是保持对自己工作和生活的掌控. 被记录的休息是战术, 而无意识的休息是对时间的浪费.
    3. Cache: 包括最近工作的所有中间文档产物, 这一区域允许混乱和无意识记录.
    4. Archive: 在休息日需要对Cache中的内容进行归档, 主要分为以下几类:

      1. 可复现的工作流: 虽然ChatGPT可以给出正确的工作流建议, 但是想要在个人接触的环境中跑通工作流是需要花费大量时间的. 为了防止工作流的遗失, 以及为了能够在Hardream团队内部共享可复现工作流提高工作效率, 人们需要尽量详细地为每个工作流记录以下信息:
        1. 环境: 操作系统内核版本, 发行版版本, 包管理器版本(如conda, brew等), 涉及的开发环境管理器版本(如uv, nvm等), 开发语言版本(如C语言, Python语言等).
        2. 如果有些操作路径在文档系统中已经被维护, 可以使用文档链接语法引用, 不需要重复劳动.
      2. 项目文档: 项目文档分为设计文档和使用文档.
        1. 设计文档主要描述设计思路, 架构框图, 仓库URL, 关键细节(花费了半小时以上的时间解决问题的诀窍或者优化瓶颈的方法).
        2. 使用文档主要暴露给用户. 即使是作者, 在一个月不看自己设计的项目之后, 也会忘记自己是如何使用这个项目的. 所以写清楚使用文档, 不仅是对用户负责, 更是给作者自己一份保障.
      3. 常用的工具和先进的理论:
        1. 使用这个工具或理论的场景和原因.
        2. 必须在文档中给出一个具体的操作案例.
    5. 总体来说, 文档系统的目录和组织结构推荐如下:

      - ToDo.md
      - Record.md
      - Cache
      - Archive
          - Workflows
          - Projects
          - Tools
          - Theories
      

文档软件

这里推荐Typora.

Jeek曾经使用过: Typora, Marktext, Ghostwriter, VSCode 以及 Obsidian.

最终发现, 文档软件所需要的最小功能就是:

  • 舒适的编辑体验
  • Markdown预览
  • 文件树,文件跳转和Link跳转支持
  • 内容搜索

其余的功能都可以通过其他软件工具来实现.

  • Typora是满足以上最小功能的最小软件.
  • Marktext功能不足且多年无人维护.
  • Ghostwriter对于图床和文件跳转的支持比较差.
  • VSCode配置好文档功能的终极形态是Typora.
  • Obsidian过于臃肿, 且编辑模式下显示有bug长期未修复.

Warning

如果大家发现了新的好用的文档软件欢迎提出issue.

有关Typora的具体使用方法请见Typora使用文档.

团队文档静态站点

对于团队文档静态站点的要求:

  1. 使用方面

    1. 在中国境内易于访问
    2. 界面美观工整
    3. 支持分类和搜索功能
  2. 维护方面

    1. 静态站点的内容来自于团队文档仓库,团队MD文档的收集、整理和更新在gitea仓库层面进行.
    2. 能够自动化从团队文档仓库转化成静态站点.

目前Hardream团队的文档静态站点采用如下技术架构维护:

flowchart TD
subgraph 内部文档仓库
    团队成员
    Github
end
subgraph 团队服务器
    zensical
    Nginx
end
subgraph 互联网
    中国用户
end
团队成员-->|MD文档|Github-->|Actions|zensical-->|site|Nginx
中国用户<-->|备案后的域名|Nginx

内部文档仓库维护方案

目前统一提交MD文档和图片的压缩包给文档管理员.

由文档管理员统一收集、整理、部署.

Warning

欢迎向文档管理员提出更好的文档管理方案.

目前的文档管理尚未实现上文的结构, 实际采用本节的方案.

本节的方案只是一个过渡方案.

仓库源文件地址: https://gitservice.cstcloud.cn/Hardream/HardreamDocs

Zensical安装与部署

Note

请文档管理员详细阅读Zensical官方文档,本文只会给出Zensical相关的最常用工作流.

Zensical是一个静态站点生成工具.

通过uv安装Zensical

Note

本文编写时的软件版本:

uv – 0.10.12

python – 3.12

zensical – 0.0.28

mkdir HardreamDocs
cd HardreamDocs
uv venv --python 3.12 venv
uv init
uv add --dev zensical

初始化Site并本地预览

zensical new . 初始化zensical文档仓库后会得到最小结构如下:

.
├─ .github/
├─ docs/
│  ├─ index.md
│  └─ markdown.md
└─ zensical.toml
  • zensical.toml是zensical后续生成site需要使用的配置文档.
  • docs文件夹下是zensical用于生成site的文档源文件.
  • .github文件夹用于自动化部署.

zensical serve 将会在本地开启一个site服务器, 可以通过打开http://localhost:8000预览当前的文档静态站点.

部署Site

写好最基础的zensical.toml

[project]

# The site_name is shown in the page header and the browser window title
site_name = "Hardream"

# The site_description is included in the HTML head and should contain a
# meaningful description of the site content for use by search engines.
site_description = "For communication and learning within the Hardream team."

# The site_author attribute. This is used in the HTML head element.
site_author = "all members of the Hardream team"

site_url = "https://hllm.tech"

# The copyright notice appears in the page footer and can contain an HTML
# fragment.
copyright = """
Copyright © 2026 Hardream. All rights reserved.
"""

zensical buildsite/下生成静态站点文件.

购买域名并域名备案

Note

本文使用腾讯云作为案例, 其他的云服务厂商场景也可以参考本文.

在腾讯云购买域名并进入腾讯云官网点击备案.

备案

填写信息进行备案.

image-20260324142800127

租用云服务器并部署

在腾讯云选购价格合理的轻量应用服务器.

然后进入腾讯云控制台找到轻量应用服务器界面.

image-20260324180619675

然后选择Ubuntu 22.04 LTS操作系统进行重装.

image-20260324180745305

image-20260324180840392

点击登录.

image-20260324181025020

在服务器中创建site资源目录.

sudo mkdir -p /var/www/zensical-site
sudo chown -R $USER:$USER /var/www/zensical-site

passwd为root用户设置密码.

然后从本地上传静态站点文件 rsync -av --delete site/ root@<server>:/var/www/zensical-site/.

  • rsync是一个常用的文件同步工具,比 scp 更适合做部署,因为它会比较文件差异,只传需要更新的部分.

  • -a表示 archive 模式。这是部署时很常用的参数,意思是尽量保留文件属性,并递归复制整个目录结构.可以把它理解成“按目录原样同步”.

  • -v表示 verbose,也就是显示详细输出。执行时能看到哪些文件被传了,方便检查.

  • --delete表示如果远程目录里有某些文件,本地 site/ 里已经没有了,那远程这些多出来的文件也会被删除.

  • site/本地源目录.

    • site/ 的意思是同步 site 目录里面的内容.

    • 如果写成 site,效果会不同,通常会把整个 site 目录本身复制过去.

为服务其安装Nginx.

sudo apt update
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl status nginx

安装成功后, 如下图所示.

image-20260324192934495

然后为nginx站点进行配置, 使用sudo vim /etc/nginx/sites-available/zensical-site新建配置文件.

server {
    listen 80;
    listen [::]:80;
    server_name docs.example.com;

    root /var/www/zensical-site;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
  • server指新建一个虚拟主机配置
  • listen 80监听IPv4的80端口, listen [::]:80监听IPv6的80端口
  • 当前Http请求头里的Host是server_name后面的域名时启用这个配置
  • root表示网站的根目录, 请求中的URL会映射到这个目录
    • /index.html/var/www/zensical-site/index.html
  • index指定默认首页是index.html
  • location / { }定义对路径 / 开头的请求的处理规则
  • try_files $uri $uri/ =404;
    • 先找与请求 URI 对应的文件:$uri
    • 如果没找到,再找对应目录:$uri/
    • 还没找到,就直接返回 404

配置写入后启用配置.

sudo ln -s /etc/nginx/sites-available/zensical-site /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx

开放防火墙.

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status

然后在腾讯云服务器控制界面编辑防火墙设置. 只开放22, 80, 443端口的TCP访问.

image-20260324194803382

Tip

此时访问服务器外网ip已经可以访问site主界面.

域名解析

推荐Cloudflare的域名解析, 后续教程都与基于腾讯云DNS服务器的域名解析无关.

使用腾讯云进行域名解析

接下来将之前备案好的域名解析到刚刚设置完成的服务器的外网ip地址上.

image-20260324195543269

image-20260324195627061

image-20260324195833048

使用Cloudflare进行域名解析

登录cloudflare然后添加domain.

image-20260324233304497

image-20260324233342640

image-20260324233424197

image-20260324233447707

image-20260324233502734

image-20260324233523229

目前得到了Cloudflare的DNS服务器域名, 进入腾讯云进行替换, 在修改DNS服务器的时候选择非腾讯云DNS服务器进行设置.

image-20260324233632468

修改完成一段时间后, Cloudflare的界面应该会变化, 显示DNS服务器设置成功.

然后按照下图进入DNS记录界面设置域名解析规则.

image-20260324233154246

Certbot申请和续期证书

基于Cloudflare DNS 服务器的域名解析添加成功后, 用Certbot开启Https服务.

  • 开启Https服务需要向Let's Encrypt机构为域名申请和续期TLS/SSL证书
  • ACME是申请和续期的协议
  • Certbot是实现ACME协议的客户端

安装Certbot.

sudo apt install -y snapd
sudo snap install core
sudo snap refresh core
sudo apt-get remove -y certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot

申请证书.

sudo certbot certonly --manual --preferred-challenges dns -d hllm.tech -d www.hllm.tech
  • --manual表示手动申请.
  • --preferred-challenges dns表示使用向DNS添加指定TXT规则的方式验证对域名的掌控权.

然后Certbot会提示向Cloudflare加入一条TXT记录.

image-20260325000633705

在刚刚添加域名解析规则的界面添加Type为TXT, Name为_acme-challeng, context为刚刚Certbot给出的value.

image-20260325000854192

先不要在Certbot界面点击Enter, 需要等待其生效. 执行dig TXT _acme-challenge.hllm.tech +short进行判断, 如果命令返回的是刚刚填写的value则说明规则生效. 可以点击Enter继续. 然后为_acme-challenge.www也增加一条规则, 同样等待生效后按下Enter. 证书签发成功后显示:

image-20260325001643513

sudo vim /etc/nginx/sites-available/zensical-site将nginx的配置改成:

server {
    listen 80;
    listen [::]:80;
    server_name hllm.tech www.hllm.tech;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name hllm.tech www.hllm.tech;

    root /var/www/zensical-site;
    index index.html;

    ssl_certificate /etc/letsencrypt/live/hllm.tech/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hllm.tech/privkey.pem;

    location / {
        try_files $uri $uri/ =404;
    }
}

然后重启nginx.

sudo nginx -t
sudo systemctl reload nginx

此时应该可以通过Https协议和域名直接访问静态站点. 比如https://hllm.tech .

手动申请证书太麻烦了, 后续建议切换到自动申请:

sudo certbot --nginx -d hllm.tech -d www.hllm.tech

然后使用sudo certbot renew --dry-run验证是否可以自动续签.

日常维护流程

uv run zensical build --clean # 整理好文档后生成静态站点
rsync -av --delete site/ user@your-server:/var/www/zensical-site/ # 同步到云端

除此之外, 还需要检查如下语法格式:

  1. 缩进使用的是4个空格而非2个空格或者tab.

  2. 如果文档名称没有作为最高级标题, 则文章要作为一级标题, 其他的标题都要降一级.

  3. github style alert (admonitions) 在typora和zensical中的语法有区别, 需要迁移.

以上区别都使用大模型检查完成.