baronunread/rdyrct

GitHub: baronunread/rdyrct

一款完全运行在 Cloudflare Workers 边缘网络上的开源团队短链接与二维码管理工具,支持自定义域名、组织协作和订阅计费。

Stars: 13 | Forks: 1

# rdyrct **基于组织的短链接 + 二维码工具,完全运行在 Cloudflare 边缘网络上。** [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE) [![Built on Cloudflare Workers](https://img.shields.io/badge/Built%20on-Cloudflare%20Workers-f38020?logo=cloudflare&logoColor=white)](https://workers.cloudflare.com) [![Bun](https://img.shields.io/badge/Bun-000000?logo=bun&logoColor=white)](https://bun.sh) [![React 19](https://img.shields.io/badge/React-19-61DAFB?logo=react&logoColor=white)](https://react.dev)
## 一键部署 [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/baronunread/rdyrct) 这会从 Cloudflare 控制台配置 Worker,并可能提示您创建或选择 KV namespace 和 D1 数据库。您仍需将其 ID 粘贴到 `wrangler.jsonc` 中,设置下方的 secrets,配置 Polar,并将域名指向该 Worker;详情请参阅[部署到 Cloudflare Workers](#deploy-to-cloudflare-workers)。 ## 功能 - **短链接**:支持自定义或随机 slug,可在重定向时应用可选的 UTM 参数(source、medium、campaign、term、content)。 - **二维码**:每个链接均可生成(付费计划),中心可选添加 logo,支持实时预览以及 PNG/SVG 格式下载。 - **自定义域名** (Pro):通过 Cloudflare for SaaS 连接 `links.yourbrand.com`,并按域名划分 slug 的 namespace。 - **组织**:具有 `owner` / `admin` / `member` 角色:admin 负责管理团队、域名和计费;member 负责管理链接。 - **Magic-link 邀请**:一次性使用,有效期 7 天,通过电子邮件发送。 - **隐私友好的分析**:每日点击量、热门链接、国家/地区、来源引荐、设备。绝不存储 IP 地址。 - **按用户的 Free/Hobby/Pro 计费**:通过 [Polar](https://polar.sh) 进行,该平台作为记录商户 (Merchant of Record) 并处理税务/VAT。 - **基于 Secret 的隐藏超级管理员控制台**:匹配 `SUPERADMIN_EMAIL` 的账户将获得用于查看使用量、深入查看组织和管理计划的云端控制台面板。其他所有人访问均会返回 404。 ## 技术栈 rdyrct 是基于 Cloudflare 优先构建的:整个产品运行在单个 Worker 中,无需托管独立的后端: - **Cloudflare Workers**:一个 Worker 即可提供 API、重定向热路径和静态 React 应用。 - **D1**:边缘网络上的 SQLite,作为 auth、组织、链接、点击量和域名的唯一事实来源。 - **KV**:用于重定向热路径上的 slug → 目标地址查找,确保点击无需等待 D1。 - **R2**:按组织存储二维码 logo 图片,以不可变方式提供并进行缓存。 - **Cloudflare for SaaS**:用于为 Pro 组织的自有短链接域名提供自定义主机名。 - **Workers Rate Limiting**:对 auth、电子邮件、写入、上传、域名、计费和点击记录分别进行滥用控制。 应用层: - [Hono](https://hono.dev) 负责路由 - [BetterAuth](https://better-auth.com) 负责邮箱+密码身份验证,支持 email-OTP 验证和 PBKDF2/WebCrypto 哈希 - 基于 D1 的 [Drizzle ORM](https://orm.drizzle.team) - React 19 + Vite + [`@cloudflare/vite-plugin`](https://github.com/cloudflare/workers-sdk) - Tailwind v4 + [Base UI](https://base-ui.com) - TanStack Query + React Router - [Polar](https://polar.sh) 负责计费,[Resend](https://resend.com) 负责事务性电子邮件 ## 本地开发 ``` bun install cp .dev.vars.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` 的地址注册以解锁管理员控制台;任何其他地址均为普通用户。 - 新账户在限定于组织的页面上会看到创建组织的提示,直到他们创建了第一个组织。 - 电子邮件验证码通过 [emulate.dev](https://emulate.dev) 的 Resend 模拟器发送,而不是通过真实收件箱。读取方式: curl localhost:4000/emails -H 'authorization: Bearer test_token_admin' 并从最新消息中复制 6 位数字的验证码。 - 设置 `CF_DEV_ENV=1`(`.dev.vars.example` 中的默认值)会在本地存根 Cloudflare 自定义主机名 API:DNS 将在大约 5 秒后准备就绪,TLS 在大约 20 秒后准备就绪,因此无需真实 zone,“检查状态”即可显示相同的进度。若不设置此项,缺失 `CF_API_TOKEN` / `CF_ZONE_ID` 将直接判定失败,而不会伪造响应。 - 针对真实的 [Polar sandbox](https://sandbox.polar.sh) 账户进行计费需要一个公开 URL(`wrangler dev --remote` 或隧道),以便 webhooks 能够访问 `/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/` 中保留屏幕截图和 trace。 ## 部署到 Cloudflare Workers 倾向于手动操作,或者需要在上方的按钮点击后重新部署?请创建以下资源: ``` bunx wrangler kv namespace create LINKS bunx wrangler d1 create rdyrct bunx wrangler r2 bucket create rdyrct-qr-logos ``` 将返回的 ID 粘贴到 `wrangler.jsonc` 中: - `kv_namespaces[0].id` - `d1_databases[0].database_id` 在 `wrangler.jsonc` 中填写非机密变量: - `APP_URL=https://rdyrct.com` - `APP_HOST=rdyrct.com` - `MAIL_FROM=rdyrct ` - `POLAR_SERVER=sandbox`(或上线时使用 `production`) - `POLAR_PRO_PRODUCT_ID` — 在 Polar 中创建一个定期的 Pro 产品并粘贴其 ID - `POLAR_HOBBY_PRODUCT_ID` — 在 Polar 中创建一个定期的 Hobby 产品并粘贴其 ID - `CF_ZONE_ID` — 您的 `rdyrct.com` zone id 设置 secrets。可以逐一设置: ``` bunx wrangler secret put BETTER_AUTH_SECRET bunx wrangler secret put SUPERADMIN_EMAIL bunx wrangler secret put RESEND_API_KEY bunx wrangler secret put POLAR_ACCESS_TOKEN bunx wrangler secret put POLAR_WEBHOOK_SECRET bunx wrangler secret put CF_API_TOKEN ``` 或者使用 `cp prod.secrets.env.example prod.secrets.env` 批量设置,填写内容后执行: ``` bunx wrangler secret bulk prod.secrets.env && rm prod.secrets.env ``` 然后执行迁移并发布: ``` bun run db:migrate:remote bun run deploy ``` **Polar 设置:**创建一个具有 `checkouts:write` 和 `customer_sessions:write` 权限范围的 Organization Access Token。在 `https://rdyrct.com/api/webhooks/polar` 添加一个 webhook endpoint,并订阅 `subscription.active`、`subscription.revoked`、`subscription.canceled` 和 `subscription.uncanceled`。 最后,将 `rdyrct.com` 作为**自定义域名**指向 Worker:Cloudflare dashboard → Workers → 您的 worker → **Settings → Domains & Routes**。短链接位于根目录(`https://rdyrct.com/`);应用程序在其他所有路径上提供服务。 在进行首次生产环境部署之前,请查阅[速率限制策略、监控、WAF 规则和回滚步骤](docs/rate-limiting.md)。 在更改链接、域名、logo 或组织的删除流程之前,请查阅[存储恢复和对账指南](docs/storage-recovery.md)。 **客户自定义域名 (Pro):**要允许组织使用 `links.theirbrand.com`,请在 `rdyrct.com` zone 上启用 [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/),创建一个无源代理的回退源站(例如 `fallback.rdyrct.com AAAA 100::`),并添加指向 `rdyrct` worker 的 Worker 路由 `*/*`。`CF_API_TOKEN` 需要具有范围限定于该 zone 的 **Zone → SSL and Certificates → Edit** 权限。此外,请在 [Resend](https://resend.com) 中验证您的发送域(例如 `mail.rdyrct.com`),以免事务性邮件被拦截。 ## 配置 | 名称 | 类型 | 用途 | | ------------------------ | -------------- | ---------------------------------------------------------------------------------- | | `BETTER_AUTH_SECRET` | secret | 签署 session 和 token | | `SUPERADMIN_EMAIL` | secret | 成为平台管理员的账户 | | `RESEND_API_KEY` | secret | 用于事务性邮件的 Resend API key | | `POLAR_ACCESS_TOKEN` | secret | Polar API access token(范围:`checkouts:write`、`customer_sessions:write`) | | `POLAR_WEBHOOK_SECRET` | secret | 验证 Polar webhook 签名;endpoint `https://rdyrct.com/api/webhooks/polar` | | `CF_API_TOKEN` | secret | 具有 **Zone → SSL and Certificates → Edit** 权限的 Cloudflare token(自定义域名) | | `APP_URL` | var | 应用的完整公开 URL,例如 `https://rdyrct.com` | | `APP_HOST` | var | 公开主机名,例如 `rdyrct.com` | | `MAIL_FROM` | var | 发件邮件的发件人地址 | | `RESEND_BASE_URL` | var (仅限开发) | 指向本地 Resend 模拟器 | | `POLAR_SERVER` | var | `sandbox` 或 `production` | | `POLAR_PRO_PRODUCT_ID` | var | Pro 计划的 Polar product id | | `POLAR_HOBBY_PRODUCT_ID` | var | Hobby 计划的 Polar product id | | `CF_ZONE_ID` | var | 用于 Custom Hostnames 的 zone id | | `CF_DEV_ENV` | var (仅限开发) | 设置为 `1` 以伪造 Custom Hostnames API,而不是调用 Cloudflare | 在生产环境中使用 `wrangler secret put NAME` 或 `wrangler secret bulk prod.secrets.env` 设置 secrets;在本地环境中,它们全部来自 `.dev.vars`(参见 `.dev.vars.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](LICENSE)。
标签:React, Syscalls, 二维码, 团队协作, 短链接, 程序员工具, 网站分析, 自动化攻击