我构建了一个 CLI,告诉你你的开源项目符合哪些免费福利

发布: (2026年3月16日 GMT+8 08:33)
9 分钟阅读
原文: Dev.to

Source: Dev.to

TL;DR: 开源维护者因为没有人把所有免费额度和工具聚合起来,导致错失成千上万美元的免费信用和工具。我构建了 OSS Perks – 一个网站 + CLI,列出 15+ 家供应商的福利计划,并只需一条命令即可检查你的仓库是否符合资格。

问题

Vercel、Sentry、JetBrains、Cloudflare——它们都向 OSS 维护者提供免费资源:

  • $3,600 的托管积分
  • 500 万次错误事件
  • 无限的 IDE 许可证

没有人知道其中一半。

所有这些优惠分散在不同的网站上,埋藏在营销页面里,各自有不同的资格规则和申请步骤。我花了一个周末在 Google 上搜索“开源免费工具”,在标签页之间切换,试图弄清楚我的项目符合哪些条件。

随后,我看到了 getfirstcheck.com,作者是 @5harath ——一个为创始人提供免费积分和资助的创业项目目录。看到发布推文后,我恍然大悟:创始人有 firstcheck,但 OSS 维护者却没有类似的东西

于是我创建了 OSS Perks

它是什么

两件事:

  1. 一个网站 – 可搜索的 OSS 福利计划目录,提供 9 种语言。
  2. 一个 CLI – 在任意仓库运行 ossperks check,它会告诉你符合哪些福利。

OSS Perks overview

Source:

架构

ossperks/
├── packages/
│   ├── data/          # JSON 程序 + Zod 架构
│   └── cli/           # 检查资格的 CLI
├── docs/              # Next.js 16 + Fumadocs 网站
└── pnpm-workspace.yaml

核心理念:@ossperks/data唯一可信来源。每个项目都是一个 JSON 文件,例如:

{
  "slug": "vercel",
  "name": "Vercel for Open Source",
  "provider": "Vercel",
  "url": "https://vercel.com/open-source-program",
  "category": "hosting",
  "description": "Vercel provides platform credits, community support, and an OSS Starter Pack.",
  "perks": [
    {
      "title": "$3,600 Platform Credits",
      "description": "$3,600 in Vercel platform credits distributed over 12 months."
    },
    {
      "title": "OSS Starter Pack",
      "description": "Credits from third‑party services to boost your project."
    }
  ],
  "eligibility": [
    "Must be an open-source project that is actively developed and maintained.",
    "Must show measurable impact or growth potential.",
    "Must follow a Code of Conduct.",
    "Credits must be used exclusively for open-source work."
  ],
  "duration": "12 months",
  "tags": ["hosting", "deployment", "serverless", "credits"]
}

这个单一文件会被用于三件事:

  • 网站 – 渲染项目页面。
  • CLI – 用于 listshowsearch
  • 构建脚本 – 将其转换为 MDX,然后 lingo.dev 将其翻译成另外 8 种语言。

修改 JSON,所有内容都会随之更新。

核心技巧:资格检查

ossperks check 会从 GitHub/GitLab 读取你的仓库元数据,并将每条资格规则通过一系列匹配器进行处理。

const matchRule = (rule: string, ctx: RepoContext): RuleVerdict =>
  checkSubjective(rule, ctx) ??
  checkProvider(rule, ctx) ??
  checkStars(rule, ctx) ??
  checkActivity(rule, ctx) ??
  checkLicense(rule, ctx) ??
  checkRepoAttrs(rule, ctx) ?? { reason: rule, verdict: "unknown" };

每个检查器都会对人类可读的资格字符串使用正则表达式,以推断规则类型,然后针对仓库进行验证。示例——许可证检查器:

const checkLicense = (rule: string, ctx: RepoContext): RuleVerdict | null => {
  const label = ctx.license ?? "no detected license";

  if (/permissive\s+(?:open[\s-]?source\s+)?licen[sc]e/i.test(rule)) {
    return isPermissive(ctx.license)
      ? { verdict: "pass" }
      : {
          reason: `requires a permissive license (detected: ${label})`,
          verdict: "fail",
        };
  }

  if (/open[\s-]?source\s+licen[sc]e|recognized\s+licen[sc]e/i.test(rule)) {
    return isOsiApproved(ctx.license)
      ? { verdict: "pass" }
      : {
          reason: `requires an OSI‑approved license (detected: ${label})`,
          verdict: "fail",
        };
  }

  return null;
};

不需要为特定项目编写 if 语句——资格规则以 JSON 中的字符串形式存在,引擎会对意图进行模式匹配并检查仓库。添加新项目只需放入一个新的 JSON 文件;检查器会自动处理。

示例输出:

✔ next.js — MIT · 131,247 stars · last push today

Eligibility across 15 programs — 8 eligible, 5 need review, 2 ineligible

  ✔ vercel            eligible
  ✔ sentry            eligible
  ✔ github-copilot    eligible
  ✔ jetbrains         eligible
  ⚠ cloudflare        needs review
     • non‑commercial requirement cannot be auto‑verified
  ✖ browserstack      ineligible
     • requires 500+ stars (you have 42)

数据管道:JSON → 9 种语言

packages/data/src/programs/*.json     (真相唯一来源)


docs/scripts/generate-programs-mdx   (将 JSON 转换为 MDX)


lingo.dev                           (将 MDX 翻译成另外 8 种语言)

该管道确保每个项目页面都能在所有受支持的语言中使用,同步保持唯一的真相来源。

.mjs  (JSON → MDX)


docs/content/programs/en/*.mdx        (英文)

          ▼  lingo.dev
docs/content/programs/{es,fr,de,ja,ko,zh-CN,pt-BR,ru}/*.mdx

生成脚本

生成脚本会从每个 JSON 项目构建结构化的 Markdown:

const buildMarkdownBody = (p) => {
  const sections = [
    buildMetaSection(p),
    buildPerksSection(p),
    buildEligibilitySection(p),
    buildRequirementsSection(p),
    buildApplicationProcessSection(p),
    buildTagsSection(p),
  ].filter(Boolean);
  return sections.join("\n\n");
};

网站上的解析

在网站上,翻译后的 MDX 会被解析回结构化数据以供渲染:

const parsePerks = (
  section: string
): { title: string; description: string }[] =>
  section
    .split("\n")
    .filter((l) => /^-\s+\*\*/.test(l.trim()))
    .map((line) => {
      const match = line.match(/\*\*(.+?)\*\*\s*[::]\s*(.*)/);
      return match
        ? { description: match[2], title: match[1] }
        : { description: "", title: line };
    });

注意: JSON → MDX → 再解析回结构化数据是一次往返过程。实际的决定是让 lingo.dev 翻译 MDX 文件,而不是直接翻译原始 JSON。

为什么选择这个技术栈

方法

StackReason
Static site + JSON API没有 i18n,且没有文档框架
Astro在大规模时 i18n 生态系统较少
Docusaurus较重,仅支持当时的 React 18
Fumadocs + Next.js 16 (chosen)免费 i18n、MDX、OG 图片、搜索。开箱即用地提供带语言前缀的路由、语言切换、OG 图片生成以及每种语言的内容源。
Commander标准的 CLI 库

使用 Zod 进行验证

每个程序在导入时都会经过 Zod 检验。错误的 JSON 会立即报错:

export const programSchema = z.object({
  applicationProcess: z.array(z.string()).optional(),
  applicationUrl: z.string().url().optional(),
  category: categoryEnum,
  contact: contactSchema.optional(),
  description: z.string(),
  duration: z.string().optional(),
  eligibility: z.array(z.string()),
  name: z.string(),
  perks: z.array(perkSchema),
  provider: z.string(),
  requirements: z.array(z.string()).optional(),
  slug: z.string(),
  tags: z.array(z.string()).optional(),
  url: z.string().url(),
});

export const programs: Program[] = raw.map((p) => programSchema.parse(p));

权衡

  • MDX round‑trip – JSON → MDX → 解析回来的过程有点尴尬,但这是必要的,因为 lingo.dev 翻译的是 MDX,而不是 JSON。
  • Regex eligibility matching – 该方法适用于当前的 15 个项目,但较为脆弱;使用结构化规则会在长期内更为稳健。
  • No auth by default – CLI 默认未认证地访问 GitHub API,可能会触发速率限制。设置 GITHUB_TOKEN 可避免此问题。
  • Limited program count – 目前仅收录了 15 个项目;还有数十个(DigitalOcean、AWS、MongoDB、Datadog 等)只需添加对应的 JSON 文件即可。

试一试

网站

git clone https://github.com/Aniket-508/ossperks.git
cd ossperks
pnpm install
pnpm --filter docs dev

CLI

npx @ossperks/cli

# Check the current repo
ossperks check

# Check a specific repo
ossperks check --repo vercel/next.js

# List all programs
ossperks list

# Search
ossperks search hosting

# Show program details
ossperks show vercel

接下来构建什么

如果你 fork 了此仓库:

  • 添加项目 – 创建一个 {slug}.json 并提交 PR。就是这么简单。
  • 结构化资格规则 – 用类似 { "type": "min-stars", "value": 500 } 的对象替换自由文本,使检查器不依赖正则表达式。
  • GitHub Action – 在 CI 中运行 ossperks check 并将结果作为 PR 评论发布。
  • 过期跟踪 – 许多福利在 12 个月后失效;提醒功能会很有帮助。
  • 社区提交 – API 路径 (/api/submit-program) 已经存在。

如果您维护开源项目,请运行 npx @ossperks/cli check。您可能会惊讶于自己符合哪些福利。

链接

  • GitHub:
  • Website:
  • NPM:

知道缺少的程序吗? 打开一个 issue 或添加一个 JSON 文件。大约需要 5 分钟。

0 浏览
Back to Blog

相关文章

阅读更多 »