Skip to content

chore(infra): migrate desktop web to Cloudflare#4869

Merged
DIYgod merged 2 commits intodevfrom
DIYgod/migrate-to-cloudflare
Feb 22, 2026
Merged

chore(infra): migrate desktop web to Cloudflare#4869
DIYgod merged 2 commits intodevfrom
DIYgod/migrate-to-cloudflare

Conversation

@DIYgod
Copy link
Member

@DIYgod DIYgod commented Feb 22, 2026

Summary

Replaces separate Vercel deployments (follow SPA + follow-external-ssr) with unified Cloudflare Workers + Assets deployment. Implements meta tag injection, OG image generation, and environment variable management in Hono-based Worker for Workers compatibility.

  • SPA + SSR unified: Desktop web now deploys to Cloudflare Workers with integrated Assets serving
  • Hono-based Worker: Replaces Fastify for Workers compatibility (no eval/new Function)
  • Smart routing: SSR handles /share/*, /login, auth routes; other routes fallback to SPA
  • Environment injection: Supports dev (api.dev.folo.is) and prod (api.folo.is) environments
  • CI/CD ready: GitHub Actions workflow for automatic deployment on dev/main push

Changes

  • Add Hono Worker entry point with SSR and SPA routing logic
  • Create AsyncLocalStorage-based request context shim for Fastify compatibility
  • Implement WASM-based OG image rendering with R2 font storage
  • Add Cloudflare wrangler configuration with dev/prod environments and routes
  • Create GitHub Actions workflow for automated deployments to Cloudflare
  • Add build scripts for font data generation and WASM patching

Status: Dev environment (dev.folo.is) deployed via folo-ssr-dev Worker. Prod (app.folo.is) ready pending DNS setup.

🤖 Generated with Claude Code

Replaces separate Vercel deployments (follow SPA + follow-external-ssr) with unified Cloudflare Workers + Assets deployment. Implements meta tag injection, OG image generation, and environment variable management in Hono-based Worker. Adds GitHub Actions CI/CD for automatic deployment on push to dev/main branches.

- Replace Fastify with Hono for Cloudflare Workers compatibility
- Create Worker entry point with SSR routes and SPA fallback
- Add AsyncLocalStorage-based request context shim
- Implement WASM-based OG image rendering with R2 font storage
- Split SPA and SSR routing: /share/* and auth routes use SSR, others fallback to SPA
- Add Cloudflare wrangler configuration with dev/prod environments
- Create GitHub Actions workflow for automated deployments
- Add build scripts for font data and WASM patching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@safedep
Copy link

safedep bot commented Feb 22, 2026

SafeDep Report Summary

Yellow Malicious Packages Badge Green Vulnerable Packages Badge Red Risky License Badge

⚠ 1 packages are identified as suspicious, human review is recommended.

Package Details
Package Malware Vulnerability Risky License Report
@cloudflare/workerd-linux-arm64 @ 1.20260219.0
npm pnpm-lock.yaml
⚠️ ✔️ ✔️ 🔗
@img/sharp-libvips-darwin-arm64 @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-darwin-x64 @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-linux-arm @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-linux-arm64 @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-linux-ppc64 @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-linux-riscv64 @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-linux-s390x @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-linux-x64 @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-linuxmusl-arm64 @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@img/sharp-libvips-linuxmusl-x64 @ 1.2.4
npm pnpm-lock.yaml
✔️ ✔️ 🔗
@cloudflare/kv-asset-handler @ 0.4.2
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@cloudflare/unenv-preset @ 2.14.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@cloudflare/workerd-darwin-64 @ 1.20260219.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@cloudflare/workerd-darwin-arm64 @ 1.20260219.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@cloudflare/workerd-linux-64 @ 1.20260219.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@cloudflare/workerd-windows-64 @ 1.20260219.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/colour @ 1.0.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-darwin-arm64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-darwin-x64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-linux-arm @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-linux-arm64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-linux-ppc64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-linux-riscv64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-linux-s390x @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-linux-x64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-linuxmusl-arm64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-linuxmusl-x64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-wasm32 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-win32-arm64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-win32-ia32 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@img/sharp-win32-x64 @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@poppinss/colors @ 4.1.6
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@poppinss/dumper @ 0.6.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@poppinss/exception @ 1.2.3
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@resvg/resvg-wasm @ 2.6.2
npm apps/ssr/package.json pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@sindresorhus/is @ 7.2.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
@speed-highlight/core @ 1.2.14
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
blake3-wasm @ 2.1.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
error-stack-parser-es @ 1.0.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
hono @ 4.12.1
npm apps/ssr/package.json pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
miniflare @ 4.20260219.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
sharp @ 0.34.5
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
supports-color @ 10.2.2
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
undici @ 7.18.2
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
unenv @ 2.0.0-rc.24
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
workerd @ 1.20260219.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
wrangler @ 4.67.0
npm apps/ssr/package.json pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
ws @ 8.18.0
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
youch @ 4.1.0-beta.10
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗
youch-core @ 0.3.3
npm pnpm-lock.yaml
✔️ ✔️ ✔️ 🔗

This report is generated by SafeDep Github App

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95eb0378b6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"./src/lib/og/fonts": "./src/lib/og/fonts.worker",
"../../lib/og/render-to-image": "../../lib/og/render-to-image.worker",
"./src/lib/load-env": "./src/lib/load-env.worker",
"@fastify/request-context": path.resolve(__dirname, "src/lib/worker-request-context.ts"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Import path before resolving worker alias

The worker tsdown config references path.resolve(...) without importing path, so loading this config throws ReferenceError: path is not defined and build:worker terminates before producing the Worker bundle. This blocks the Cloudflare deploy path that depends on tsdown --config tsdown.worker.config.ts succeeding.

Useful? React with 👍 / 👎.

const weight = weights.find((w) => file.includes(w.weight.toString()))
if (!weight) continue
const data = fs.readFileSync(path.join(snFontsDirPath, file))
fontsData[`sn-pro-${weight.weight}`] = data.toString("base64")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep each SN Pro subset when generating font data

This assignment keys every SN Pro file only by weight, so the 40 subset files from @fontsource/sn-pro overwrite each other and only one file per weight survives in fonts-data.ts. Because subset filenames encode different glyph ranges (latin, cyrillic, etc.) and readdirSync ordering is not guaranteed across environments, OG rendering can lose characters for scripts not present in the last-seen subset.

Useful? React with 👍 / 👎.

Worker-specific files (*.worker.ts) use Cloudflare Workers types and
generated modules that aren't available during the main tsc typecheck.
Exclude them from tsconfig since they're only used via tsdown aliases.
Also fix broken path.resolve reference in tsdown.worker.config.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@DIYgod DIYgod merged commit 81c5b9f into dev Feb 22, 2026
7 of 8 checks passed
@DIYgod DIYgod deleted the DIYgod/migrate-to-cloudflare branch February 22, 2026 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant