关于 rdyrct
rdyrct 是部署在 Cloudflare 上、以组织为单位管理短链接的服务,面向需要使用自有域名并查看点击数据的团队。它还支持链接别名、二维码和不存储 IP 地址的分析,并可部署到自己的 Cloudflare 账户。
主要功能
- 01创建自定义或随机短链接
- 02管理链接别名与 UTM 参数
- 03为链接生成并下载二维码
- 04按组织和角色管理成员
- 05查看点击、来源、地区与设备统计
适用场景
- 01为团队或组织创建品牌短链接
- 02按营销活动添加 UTM 参数并统计点击
- 03为短链接提供二维码下载
- 04查看链接访问来源和设备分布
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://rdyrct.com/api/mcpclaude mcp add --transport http baronunread-rdyrct https://rdyrct.com/api/mcp{"mcpServers":{"baronunread-rdyrct":{"type":"http","url":"https://rdyrct.com/api/mcp"}}}在 Cursor 中打开{"servers":{"baronunread-rdyrct":{"type":"http","url":"https://rdyrct.com/api/mcp"}}}在 VS Code 中打开{"mcpServers":{"baronunread-rdyrct":{"type":"http","url":"https://rdyrct.com/api/mcp"}}}{"mcpServers":{"baronunread-rdyrct":{"serverUrl":"https://rdyrct.com/api/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
一键部署
Cloudflare 会将此代码库复制到你的 GitHub 账户,创建数据库、存储和队列,并只要求你提供一项信息:将成为平台管理员的账户邮箱。其他所有值都保持原样。首次构建会通过 workers.dev 地址提供你的副本,生成会话密钥并应用迁移;此后每次推送到你的副本都会重新部署。准备好使用自己的域名时,请参阅迁移到自己的域名。
更喜欢使用终端?bun run setup 可以在克隆的代码库中完成相同操作:请参阅部署到 Cloudflare Workers。
功能
- 短链接:支持自定义或随机别名,并可选在重定向时应用 UTM 参数(来源、媒介、活动、关键词、内容)。
- 分组链接地址:重命名链接后,旧别名会继续重定向 48 小时,然后才释放;链接还可以包含多个额外别名,这些别名都会重定向到同一目标。
- 每个链接的二维码(付费套餐):可选择在中心添加徽标,支持实时预览和 PNG/SVG 下载。
- 自定义域名(Pro):通过 Cloudflare for SaaS 连接
links.yourbrand.com,并为每个域名分别设置别名命名空间。 - 组织,支持
owner/admin/member角色:管理员管理团队、域名和账单;成员管理链接。 - 魔法链接邀请:一次性使用,有效期为 7 天,通过电子邮件发送。
- 注重隐私的数据分析:每日点击量、热门链接、国家/地区、引荐来源和设备。绝不会存储 IP 地址。
- 通过 Polar 按用户提供 Free/Hobby/Pro 计费;Polar 作为登记商家处理税费/VAT。
- 密钥保护的超级管理员控制台:匹配
SUPERADMIN_EMAIL的账户会在云控制台中看到使用情况、组织详情和套餐管理面板。其他所有人访问时都会收到 404。
技术栈
rdyrct 以 Cloudflare 为核心构建:整个产品运行在单个 Worker 中,无需托管独立后端:
- Cloudflare Workers:单个 Worker 提供 API、重定向快速路径和静态 React 应用。
- D1:边缘网络上的 SQLite,是身份验证、组织、链接、点击和域名数据的唯一可信来源。
- KV:在重定向快速路径上执行别名 → 目标地址查询,因此点击请求无需等待 D1。
- R2:存储二维码徽标图片,按组织设置键名,并以不可变方式提供和缓存。
- Cloudflare for SaaS:为 Pro 组织的自有短链接域名提供自定义主机名。
- Workers Rate Limiting:分别为身份验证、电子邮件、写入、上传、域名、账单和点击记录设置滥用防护。
应用层:
- 使用 Hono 进行路由
- 使用 BetterAuth 实现邮箱+密码身份验证,并通过邮件 OTP 验证以及 PBKDF2/WebCrypto 哈希处理
- 基于 D1 使用 Drizzle ORM
- React 19 + Vite +
@cloudflare/vite-plugin - Tailwind v4 + Base UI
- TanStack Query + React Router
- 使用 Polar 处理账单,使用 Resend 发送事务性邮件
本地开发
bun install
cp .dev.vars.local.example .dev.vars # then edit; at minimum set SUPERADMIN_EMAIL
bunx emulate --service resend # local Resend inbox on :4000
bun run db:migrate:local
bun run dev # https://rdyrct.localhost
-
使用设置为
SUPERADMIN_EMAIL的邮箱地址注册,即可解锁管理控制台;任何其他邮箱地址都属于普通用户。 -
开发服务器运行的是可自托管应用。将
VITE_RDYRCT_SITE=1添加到.env,即可开发 rdyrct.com 自有的落地页和营销页面。 -
新账户在组织范围页面上会看到创建组织提示,直到创建第一个组织。
-
邮箱验证码通过 emulate.dev 的 Resend 模拟器发送,而非真实收件箱。使用以下命令读取:
curl localhost:4000/emails -H 'authorization: Bearer test_token_admin'并从最新消息中复制 6 位验证码。
-
设置
CF_DEV_ENV=simulated(.dev.vars.local.example中的默认值)会在本地模拟 Cloudflare Custom Hostnames API:DNS 大约 3 秒后就绪,TLS 大约 12 秒后就绪,因此“检查状态”会显示相同的进度,无需真实区域。CF_DEV_ENV=instant会立即报告两者都已就绪,端到端测试会使用此设置,以免等待计时器。如果两者都未设置,缺少CF_API_TOKEN/CF_ZONE_ID时会直接失败,而不会伪造响应。 -
使用真实的 Polar sandbox 账户进行计费,需要公开 URL(
wrangler dev --remote或隧道),以便 webhook 能访问/api/webhooks/polar。
测试
bun run test # fast unit tests
bun run test:worker # Worker routes with local D1 and KV bindings
bun run e2e:install # install Chromium for Playwright once
bun run e2e:smoke # real-browser baseline regression checks
bun run verify # types, lint, formatting, unit, and Worker tests
Playwright 负责本地服务器的生命周期管理,且绝不会重置或填充本地 Cloudflare 状态。浏览器测试失败时,会在 test-results/ 中保留截图和跟踪记录。
部署到 Cloudflare Workers
git clone https://github.com/baronunread/rdyrct
cd rdyrct && bun install
bun run setup
设置过程会询问三项内容:Worker 的名称(按 Enter 保留 rdyrct)、Cloudflare 账户中的域名(或按 Enter 使用免费的 *.workers.dev 地址),以及将成为平台管理员的账户邮箱。如果账户中已运行同名 Worker,设置会停止,因此绝不会覆盖已有 Worker。随后会:
- 重写你自己的
wrangler.jsonc副本:在APP_URL和APP_HOST中设置你的域名,并移除 rdyrct.com 自有的 ID 和设置(邮件发件人、Polar 产品、Cloudflare 区域、Sentry); - 让 Wrangler 在你的账户中创建 D1 数据库、KV 命名空间、R2 存储桶和队列,每项均以 Worker 命名,因为未设置 ID 的绑定会在首次部署时创建新资源;
- 生成
BETTER_AUTH_SECRET,将其和SUPERADMIN_EMAIL设置为密钥,然后构建、部署、应用迁移并绑定你的域名。
将重写后的 wrangler.jsonc 提交到你的 fork。之后,bun run deploy 会部署每次更新:先应用新迁移,再进行部署。每次构建都是可自托管应用,它会打开登录页面,且不包含 rdyrct.com 的营销页面、分析功能或搜索标签。只有设置 VITE_RDYRCT_SITE=1 才会构建 rdyrct.com 本身,而且 bun run deploy 会拒绝将其部署到 rdyrct.com 以外的主机。
其他内容均为可选。每一项都会说明它能添加什么:
| 设置 | 提供的功能 |
|---|---|
RESEND_API_KEY、MAIL_FROM | 电子邮件:注册验证码、密码重置、邀请和通知。未配置时,注册会跳过验证(见下文)。 |
POLAR_* | 销售 Hobby 和 Pro 套餐。未配置时,不会限制任何人,也不会显示账单信息。 |
GOOGLE_CLIENT_ID、GOOGLE_CLIENT_SECRET | “使用 Google 继续”。 |
CF_API_TOKEN、CF_ZONE_ID | 通过 Cloudflare for SaaS 使用客户自己的域名。 |
SHARED_LINK_HOST | 为新建的共享域名链接指定第二个、更短的主机名。 |
TURNSTILE_SITE_KEY、TURNSTILE_SECRET_KEY | 在注册、密码重置和举报表单前启用 Cloudflare Turnstile。使用一次 wrangler secret bulk 调用同时设置两项:缺少其中一项,这些表单就会被拒绝。之后 Cloudflare 会看到这些访问者。 |
WEB_RISK_API_KEY | 使用 Google Web Risk 进行第二次目标检查。若目标在列表中,其链接会被暂时搁置。 |
SENTRY_DSN | 将错误报告发送到你的 Sentry 项目。 |
SITE_NAME | 所有标签页显示的名称,例如“Acme links”。未配置时,标签页会显示你部署实例的主机名。 |
如果没有电子邮件服务提供商,也没有 Google 登录,账户就不会经过验证,密码也无法重置。 这适用于私有实例,但不建议用于公开实例。此情况存在时,管理控制台会予以提示。
变量写入 wrangler.jsonc。使用 bunx wrangler secret put <NAME> 逐个设置机密,或使用 cp prod.secrets.env.example prod.secrets.env 批量设置;填写文件后,然后:
bunx wrangler secret bulk prod.secrets.env && rm prod.secrets.env
迁移到自己的域名
是通过按钮还是设置流程在 workers.dev 上启动的?克隆你的副本,运行 bun run setup 并提供域名(该域名必须属于你的 Cloudflare 账户),然后提交 wrangler.jsonc 并推送。设置流程会绑定域名,并保留你的数据、密钥和会话密钥。也可以手动操作:Cloudflare 控制台 → Workers → 你的 Worker → Settings → Domains & Routes → Add → Custom domain,然后在 wrangler.jsonc 中设置 APP_URL 和 APP_HOST,移除 rdyrct.com 使用的变量(MAIL_FROM、WELCOME_FROM、POLAR_*、CF_ZONE_ID、SENTRY_DSN),并运行 bun run deploy。短链接位于根路径(https://links.example.com/<slug>);应用会在其他所有路径上提供服务。不要将路由写入 wrangler.jsonc:routes 列表会替换控制台中绑定的所有路由,而提交你自己的路由会将其配置应用到每个分支。*/* 路由仅供客户自己的域名使用(见下文)。
邮件(可选)
设置 RESEND_API_KEY 和 MAIL_FROM(发件人地址的域名需已在 Resend 中验证)。不设置这些变量就不会发送邮件:注册时会跳过验证码并直接登录用户,密码重置表单则会提示需要邮件服务提供商。邮件发送逻辑集中在一个函数中:src/worker/email.ts 里的 sendEmail();要更换服务提供商,只需修改该函数。
销售方案(可选)
跳过本节即可在没有上限且不计费的情况下运行。要销售方案,请设置 POLAR_SERVER=sandbox(正式上线后设为 production)、POLAR_PRO_PRODUCT_ID 和 POLAR_HOBBY_PRODUCT_ID(在 Polar 中创建的定期订阅产品),以及密钥 POLAR_ACCESS_TOKEN 和 POLAR_WEBHOOK_SECRET。
**Polar 设置:**创建一个具有 checkouts:write 和 customer_sessions:write 权限范围的 Organization Access Token。添加 webhook 端点 https://rdyrct.com/api/webhooks/polar,并订阅 Worker 处理的全部五种事件。漏掉任何一种都会导致计费状态不一致:
| 事件 | 作用 |
|---|---|
subscription.active | 开始订阅:方案、客户、价格和访问权限 |
subscription.updated | 完整的订阅快照:状态、产品、取消状态和周期结束时间 |
subscription.canceled | 将订阅标记为在周期结束时终止;在此之前仍可访问 |
subscription.uncanceled | 清除已安排的取消 |
subscription.revoked | 终止订阅:订阅及其访问权限一并失效 |
哪些订阅状态可以保留访问权限,是 src/worker/entitlement.ts 中的一项配置。active、trialing 和 past_due 状态会保留访问权限,因为 Polar 会对失败的付款重试数天,并在放弃重试时发送 subscription.revoked。unpaid、canceled、incomplete 和 incomplete_expired 状态不会保留访问权限;未配置规则的状态也不会保留访问权限。
管理员手动授予的付费访问权限属于赠送权限,与订阅分开存储,且不会计为订阅用户。赠送权限优先于其下方的订阅,因此撤销订阅不会取消管理员授予的访问权限。
管理控制台报告的是数量,而非金额:有多少人拥有付费方案、有多少人为此付费,以及有多少人获得了赠送权限。谁正在取消订阅,会显示在用户列表中对应用户的那一行。收入请查看 Polar 控制面板,该面板记录了扣除折扣、税费和退款后的实际收费金额。
**第二个共享域名主机(可选)。**以相同方式绑定一个更短的域名,确认 https://<it>/ 会返回重定向,然后再通过 bunx wrangler secret put SHARED_LINK_HOST 启用它。无需部署即可生效;运行 bunx wrangler secret delete SHARED_LINK_HOST 即可关闭。请按此顺序操作,因为每个新链接都会立即开始使用该域名:如果在域名解析生效前设置,就会发放无法访问的链接。旧链接在两个主机上都能继续使用,因为共享域名的 slug 所对应的 KV 键不包含主机名。未设置时,共享链接会使用 APP_HOST。
首次部署到生产环境前,请查看速率限制策略、监控、WAF 规则和回滚步骤。
更改链接、域名、徽标或组织删除流程前,请查看架构、数据流和改进优先级。
**客户自定义域名(Pro):**若要允许组织使用 links.theirbrand.com,请在 rdyrct.com 区域启用 Cloudflare for SaaS,创建一个没有源站的代理回退源站(例如 fallback.rdyrct.com AAAA 100::),并添加指向 rdyrct Worker 的 Worker 路由 */*。CF_API_TOKEN 需要具有 Zone → SSL and Certificates → Edit 权限,且权限范围限定为该区域。此外,请在 Resend 中验证你的发信域名(例如 mail.rdyrct.com),以免事务性邮件被拦截。
配置
| 名称 | 类型 | 用途 |
|---|---|---|
BETTER_AUTH_SECRET | 密钥 | 为会话和令牌签名 |
SUPERADMIN_EMAIL | 密钥 | 将成为平台管理员的账户 |
RESEND_API_KEY | 密钥 | 用于事务性邮件的 Resend API 密钥 |
POLAR_ACCESS_TOKEN | 密钥 | Polar API 访问令牌(作用域:checkouts:write、customer_sessions:write) |
POLAR_WEBHOOK_SECRET | 密钥 | 验证 Polar webhook 签名;端点 https://rdyrct.com/api/webhooks/polar |
CF_API_TOKEN | 密钥 | 具有 Zone → SSL and Certificates → Edit 权限的 Cloudflare 令牌(自定义域名) |
APP_URL | 变量 | 应用的完整公开 URL,例如 https://rdyrct.com |
APP_HOST | 变量 | 公开主机,例如 rdyrct.com |
SHARED_LINK_HOST | 密钥(可选) | 新链接使用的第二个共享域名主机,例如 rdyr.cc;解析成功后设置 |
MAIL_FROM | 变量 | 发出邮件的发件人地址 |
RESEND_BASE_URL | 变量(仅开发环境) | 指向本地 Resend 模拟器 |
POLAR_SERVER | 变量 | sandbox 或 production |
POLAR_PRO_PRODUCT_ID | 变量 | Pro 套餐的 Polar 产品 ID |
POLAR_HOBBY_PRODUCT_ID | 变量 | Hobby 套餐的 Polar 产品 ID |
CF_ZONE_ID | 变量 | 用于 Custom Hostnames 的 Zone ID |
CF_DEV_ENV | 变量(仅开发环境) | simulated 会通过定时器模拟 Custom Hostnames API,instant 则不使用定时器 |
生产环境中,使用 wrangler secret put NAME 或 wrangler secret bulk prod.secrets.env 设置密钥;本地环境中,所有密钥均来自 .dev.vars(参见 .dev.vars.local.example)。
项目结构
migrations/ D1 schema (numbered SQL migrations, applied in order)
scripts/ Local dev utilities (e.g. seed-local.ts)
src/worker/ Hono API, BetterAuth, KV publishing, redirect hot path
routes/ auth/user, orgs, links, qr-logos, domains, billing, admin
better-auth.ts plan.ts util.ts guards.ts org-role.ts rate-limit.ts session.ts
email.ts password.ts kv.ts storage.ts alerts.ts clicks.ts workflows.ts
src/shared/types.ts DTOs + PLAN_LIMITS (shared worker ↔ app)
src/app/ React SPA
routes/ page-level route components
ui/ design-system primitives
components/ feature components
lib/ client utilities, API hooks
.agents/skills/ Agent skills (react-doctor)
.claude/skills/ Claude skills (fallow, react-doctor)
许可证
MIT © Andrea Bruno。详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。