remote-jobs 仓库中的 Plai 公司档案:frontmatter 元数据建模与远程公司目录的构建解析
remote-jobs 仓库中的 Plai 公司档案:frontmatter 元数据建模与远程公司目录的构建解析
导读
本文以 src/companies/plai.md 这份公司档案为样本,拆解 remoteintech.company 开源目录(即 GitHub_Trending/re/remote-jobs 仓库)中"公司档案"这类数据文件的完整结构:从 frontmatter 字段的取值约定、正文小节规范,到这些数据被 Eleventy 构建系统读取后如何生成可浏览的公司页面与标签索引。读完本文,你将掌握该仓库公司档案的数据建模方式,能够独立读懂或编写一份符合规范的公司档案文件,并理解 frontmatter 中的每个字段最终在站点上如何呈现。
一、档案全貌:一份公司档案文件包含什么
plai.md 是远程技术公司目录中一份典型的公司档案,位于 src/companies/ 目录下。文件由两大部分组成:frontmatter(YAML 元数据块) 与 Markdown 正文。
frontmatter 部分完整内容如下(继承自原档案,字段值与 CONTRIBUTING.md 提供的模板完全对齐):
---
title: "Plai"
slug: plai
website: https://plai.team
region: americas-europe
remote_policy: remote-friendly
company_size: tiny
technologies:
- devops
- java
- javascript
addedAt: 2020-07-19
updatedAt: 2020-07-19
---
正文部分则按 ## 小节组织:Company blurb(公司简介)、Company size(规模)、Remote status(远程状态)、Region(地区)、Company technologies(技术栈)、Office locations(办公地点)、How to apply(如何申请)。
从 README.md 可知,本仓库是 remoteintech.company 站点的源代码,通过 Eleventy 静态构建把 src/companies/**/*.md 下的每份档案渲染为独立公司页面。{slug}.md 的文件名必须与 frontmatter 中的 slug 值一致(例如 slug: plai 对应 src/companies/plai.md),这是 CONTRIBUTING.md 明确要求的硬性约定,也是后续集合聚合、URL 生成的基础。
二、frontmatter 字段逐一拆解:取值从哪来、呈现成什么
档案的元数据字段并非自由发挥,而是受中央定义约束。仓库把字段的合法取值集中定义在 src/_data/labels.js 中,并在 src/_data/companyHelpers.js 中将其 re-export 给 JS 消费方;CONTRIBUTING.md 则用一张表记录了各字段的合法值范围。结合三处证据,可得到 Plai 档案各字段的完整映射:
| 字段 | Plai 档案取值 | 合法取值(来源) | 在站点上的呈现 |
|---|---|---|---|
title |
Plai |
任意公司名 | 页面 H1 标题、排序依据、meta description |
slug |
plai |
必须与文件名一致 | URL 段 /companies/plai/ |
website |
plai.team |
公司官网 | 页面主按钮"Visit Website"的跳转地址 |
region |
americas-europe |
worldwide / americas / europe / americas-europe / asia-pacific / other |
"Americas & Europe" 地区标签,链接到 /browse/americas-europe/ |
remote_policy |
remote-friendly |
fully-remote / remote-first / hybrid / remote-friendly |
"Remote Friendly" 政策标签,链接到 /browse/remote-friendly/ |
company_size |
tiny |
tiny(1-10) / small(11-50) / medium(51-200) / large(201-1000) / enterprise(1000+) |
规模标签(tiny 对应 "1-10 employees") |
technologies |
devops / java / javascript |
见 src/_data/labels.js 的 tech 表(如 react、nodejs、go 等 24 项) |
技术标签,链接到 /browse/{tech}/ 浏览页 |
addedAt / updatedAt |
2020-07-19 |
由维护者管理,贡献者 PR 中不应包含 | 页面页脚展示"Last updated",并参与"最近添加"排序 |
几个值得注意的实现细节:
- 标签文案来自单一事实源:
americas-europe、remote-friendly、tiny这些机器可读的枚举值,其人类可读文案("Americas & Europe"、"Remote Friendly"、"1-10 employees")统一由 src/_data/labels.js 提供。渲染层通过labels.region[region]、labels.remotePolicy[remote_policy]、labels.companySize[company_size]取值;src/_data/companyHelpers.js 中的getRegionLabel()、getRemotePolicyLabel()、getCompanySizeLabel()、getTechLabel()则把同一映射提供给 JS 侧的集合与标签生成逻辑,避免两处文案漂移。 careers_url是可选的锦上添花字段:CONTRIBUTING.md 的模板中提供了careers_url(指向公司自己的招聘页)。Plai 档案未填写该字段,因此页面主按钮会回退为使用website并显示"Visit Website"——这一回退逻辑在 src/_layouts/company.njk 中以{% set buttonUrl = careers_url or website %}实现:优先careers_url(按钮文案 "Apply Now"),否则用website(按钮文案 "Visit Website")。
三、正文小节解析:Plai 档案的七段结构与信息要点
档案正文承载了机器可读元数据无法表达的叙事性信息。Plai 档案的正文可以逐段解读如下:
Company blurb(公司简介)
Plai 是一家面向远程公司的人员与绩效管理公司,帮助组织用 OKR 对齐团队、以反馈与表扬驱动成长、提供流畅的绩效 / 360° 评审和高效的 1:1 会议。
这是全文的信息锚点。src/companies/companies.11tydata.js 中的 Eleventy Computed 逻辑会自动从该小节生成页面的 meta description:它通过正则 ##\s*Company\s*blurb\s*\n+([\s\S]*?)(?=\n##|$) 提取 blurb 文本,剥掉 Markdown 链接语法(text → text)、去除 * _ ` 与多余空白,再截断到约 155 字符并尽量在句号处收尾。这意味着写好 blurb 直接决定公司页在搜索引擎中的摘要质量——Plai 档案未手工设置 description 字段,因此其页面描述完全由这一机制自动派生。
Company size(公司规模)
2020 年夏季为 10 人,并快速增长中。
注意这段描述与 frontmatter 中 company_size: tiny("1-10 employees")相互印证:正文记录的是当时的快照口径,元数据则提供了可枚举、可聚合的规模区间。两者共同呈现"规模标签 + 具体人数"的完整信息。
Remote status(远程状态)
团队中一半成员远程办公,多数成员来自乌克兰的不同城市;日常通过 Slack / Google Meet 沟通,并使用自家产品 Plai 来保持团队对齐。
这段说明了几层信息:远程比例(约 50%)、地理分布(乌克兰多城市分布式)、协作工具栈(Slack / Google Meet)、以及"吃自己的狗粮"——用自家的人效管理工具做内部对齐,与 blurb 中"帮助远程公司管理 OKR、反馈、1:1"的产品定位直接闭环。
Region(地区)
欧洲和北美。
与 frontmatter 的 region: americas-europe 枚举一致,标签渲染为 "Americas & Europe"。该字段的职责是支撑 src/_config/collections.js 中的 getCompaniesByRegion() 分组聚合——所有档案按 region 归入 worldwide、americas、europe、americas-europe、asia-pacific、other 六个桶,供 /browse/{region}/ 浏览页使用。
Company technologies(公司技术栈)
原档案以四行要点列出技术栈:
- 前端:React
- 后端:Kotlin/Spring、NodeJS/Nest(NX mono-repo)
- 运维(DevOps):AWS、Terraform、ansible
这里存在一个值得注意的数据建模分层:正文用自然语言描述完整技术栈(含 Kotlin、Spring、NX、Terraform、ansible 等细项),而 frontmatter 的 technologies 只登记了 devops、java、javascript 三个枚举标签——因为只有枚举值才能被 src/_config/collections.js 的 getCompaniesByTech() 识别并聚合进 /browse/{tech}/ 标签页。所以实际目录浏览时,Plai 会出现在 DevOps、Java、JavaScript 三个技术浏览页下;而正文保留的细粒度信息则服务人类读者的阅读。
Office locations(办公地点)
乌克兰基辅。
作为一家半数远程的公司,Plai 以基辅为实体办公所在地,属于"远程友好"(remote-friendly)而非"完全远程"(fully-remote)的典型形态——有实体办公室,但允许并支持远程协作。
How to apply(如何申请)
指向 Plai 的团队介绍页。
按照 CONTRIBUTING.md 的规范,How to apply 是每个档案的必需小节,且 careers_url 应指向公司自己的招聘页而非外包/代理页面。Plai 档案未提供独立的 careers 链接,因此读者需通过页面主按钮进入官网后寻找招聘信息。
四、从一份档案到完整页面:构建管线如何消费 plai.md
理解完数据本身,再看这份档案如何被站点渲染与索引。整条链路在仓库中清晰可循:
- 文件收集:src/_config/collections.js 通过
collection.getFilteredByGlob('./src/companies/**/*.md')收集全部公司档案,结果被缓存在_companyCache中(注释说明:避免对约 850 家公司反复过滤 6 次)。getAllCompanies()按title做localeCompare排序,Plai 按字母序出现在目录中。 - 集合派生:同一文件中的
getCompaniesByRegion()按region分组、getCompaniesByTech()按technologies数组逐项分组、getCompanyTags()生成含标签元数据(slug、类型、label、计数、公司列表)的标签体系,支撑/browse/浏览页。 - 页面渲染:src/companies/companies.json 声明所有公司档案统一使用
company布局;src/_layouts/company.njk 负责具体渲染——title进 H1,website/careers_url决定主按钮,region、remote_policy渲染为带浏览页链接的标签,technologies渲染为技术标签区,updatedAt通过 src/_config/filters/dates.js 的formatDate('MMMM D, YYYY')格式化为页脚日期。 - 日期处理:
addedAt参与getRecentCompanies()的"最近添加"排序(按b.data.addedAt - a.data.addedAt倒序取前 12 家);updatedAt在布局中决定是否显示"Last updated"。Plai 档案的addedAt/updatedAt同为 2020-07-19,说明该档案自录入以来未被维护者更新过,属于历史快照。
五、从 Plai 档案看目录的数据建模取舍
这份档案虽短,却完整体现了 remoteintech.company 目录的核心建模策略:
- 枚举化与自由文本分层:可聚合、可排序、可过滤的信息(地区、远程政策、规模、技术)全部枚举化并集中定义在 src/_data/labels.js;需要叙事的信息(公司做什么、远程如何协作)留给 Markdown 正文。这保证了浏览页索引的机器可读性与公司简介的人类可读性兼得。
- 单一事实源与自动派生:标签文案单一事实源(labels.js)、meta description 自动从 blurb 派生(src/companies/companies.11tydata.js)、
updatedAt自动驱动页脚日期——贡献者只需写好 frontmatter 与正文,展示层细节由构建系统补齐。 - 规范的强约束:CONTRIBUTING.md 明确
Company blurb、Remote status、How to apply为必需小节,careers_url必须指向公司自己的招聘页,addedAt/updatedAt由维护者管理。Plai 档案(2020 年录入)的结构与 2026 年的规范高度一致,从侧面说明这套格式的稳定性。
六、延伸:如何阅读与编写同类档案
如果你希望自行阅读或为目录新增公司档案,可按 CONTRIBUTING.md 的流程操作(仓库只读,此处仅说明流程而非改动仓库):
- 在
src/companies/下创建{slug}.md,slug与 frontmatter 的slug字段一致; - 按前文字段表填写 frontmatter,合法值以 src/_data/labels.js 和 CONTRIBUTING.md 的取值表为准;
- 正文至少包含
Company blurb、Remote status、How to apply三个小节,careers_url指向公司自有招聘页; - 本地执行
npm install后运行npm run build验证构建(需 Node.js 22+),再提交 PR,由 Validate Company Profiles 工作流自动校验。
以 Plai 档案为参照:枚举字段忠实记录(如远程政策取 remote-friendly 而非夸大的 fully-remote),正文快照标注时间(如"2020 年夏季 10 人"),正文技术栈与枚举标签各司其职——这正是该目录长期社区维护下依然数据一致、可机器消费的关键所在。
参考文件索引
- 档案本体:src/companies/plai.md
- 标签与取值定义:src/_data/labels.js、src/_data/companyHelpers.js
- 贡献规范与 frontmatter 模板:CONTRIBUTING.md
- 档案元数据派生:src/companies/companies.11tydata.js
- 集合与浏览页逻辑:src/_config/collections.js
- 页面布局渲染:src/_layouts/company.njk、src/companies/companies.json
- 日期格式化:src/_config/filters/dates.js
- 项目构建说明:README.md