feat: Cloudflare Workers deployment for Media Kit#487
Open
xiaomoziyi wants to merge 11 commits intomasterfrom
Open
feat: Cloudflare Workers deployment for Media Kit#487xiaomoziyi wants to merge 11 commits intomasterfrom
xiaomoziyi wants to merge 11 commits intomasterfrom
Conversation
Migrate Media Kit from Blocklet Server (Express + SQLite + local disk) to Cloudflare Workers (Hono + D1 + R2), enabling edge deployment with zero server maintenance. Backend (cloudflare/src/): - Hono API server with full upload/folder/serve/status routes - Presigned URL upload flow with multipart support - R2 file storage with MD5 content dedup - D1 database with Drizzle ORM - AIGNE Hub proxy for AI Image generation - SPA fallback for client-side routing Frontend (cloudflare/frontend/): - Reuses original blocklets/image-bin/src/ via Vite aliases - Shim layer replaces @blocklet/* and @arcblock/* SDK dependencies - window.blocklet injected in index.html for module-level access - path-browserify polyfill for browser compatibility Shared code changes (backward compatible): - uploader: support both URL and base64 for AI Image results - uploader: add presigned-upload Uppy plugin - uploader: add .catch() for AI Image URL fetch Deployed at: https://media-kit.yexiaofang.workers.dev TODO: - Replace x-user-did auth with CF auth SDK (shijun) - Restrict CORS origin after auth is ready - Production: use S3 CopyObject instead of R2 binding get+put for large files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Files selected (49)
- cloudflare/.gitignore (1)
- cloudflare/README.md (1)
- cloudflare/docs/CHANGES.md (1)
- cloudflare/docs/MIGRATION-PLAN.md (1)
- cloudflare/docs/MIGRATION-REPORT.md (1)
- cloudflare/drizzle.config.ts (1)
- cloudflare/frontend/index.html (1)
- cloudflare/frontend/src/App.tsx (1)
- cloudflare/frontend/src/api.ts (1)
- cloudflare/frontend/src/components/FolderList.tsx (1)
- cloudflare/frontend/src/components/ImageGrid.tsx (1)
- cloudflare/frontend/src/components/UploadButton.tsx (1)
- cloudflare/frontend/src/main.tsx (1)
- cloudflare/frontend/src/plugins/presigned-upload.ts (1)
- cloudflare/frontend/src/shims/arcblock-did.ts (1)
- cloudflare/frontend/src/shims/arcblock-ux.tsx (1)
- cloudflare/frontend/src/shims/blocklet-js-sdk.ts (1)
- cloudflare/frontend/src/shims/blocklet-ui-react-dashboard.tsx (1)
- cloudflare/frontend/src/shims/blocklet-ui-react-footer.tsx (1)
- cloudflare/frontend/src/shims/blocklet-ui-react-header.tsx (1)
- cloudflare/frontend/src/shims/blocklet-ui-react.tsx (1)
- cloudflare/frontend/src/shims/did-connect-react-button.tsx (1)
- cloudflare/frontend/src/shims/did-connect-react-session.tsx (1)
- cloudflare/frontend/tsconfig.json (1)
- cloudflare/frontend/vite.config.ts (1)
- cloudflare/migrations/0001_initial.sql (1)
- cloudflare/pnpm-lock.yaml (1)
- cloudflare/scripts/migrate-data.ts (1)
- cloudflare/src/tests/utils.test.ts (1)
- cloudflare/src/tests/worker.integration.ts (1)
- cloudflare/src/db/schema.ts (1)
- cloudflare/src/middleware/auth.ts (1)
- cloudflare/src/routes/cleanup.ts (1)
- cloudflare/src/routes/folders.ts (1)
- cloudflare/src/routes/serve.ts (1)
- cloudflare/src/routes/status.ts (1)
- cloudflare/src/routes/unsplash.ts (1)
- cloudflare/src/routes/upload.ts (1)
- cloudflare/src/types.ts (1)
- cloudflare/src/utils/hash.ts (1)
- cloudflare/src/utils/s3.ts (1)
- cloudflare/src/worker.ts (1)
- cloudflare/tsconfig.json (1)
- cloudflare/vitest.config.ts (1)
- cloudflare/wrangler.toml (1)
- packages/uploader/src/react/plugins/ai-image/show-panel/output/index.tsx (1)
- packages/uploader/src/react/plugins/presigned-upload.ts (1)
- packages/uploader/src/react/uploader.tsx (8)
- pnpm-lock.yaml (21)
Files ignored due to filter (2)
- cloudflare/frontend/package.json
- cloudflare/package.json
Files not summarized due to errors (49)
- cloudflare/drizzle.config.ts (nothing obtained from anthropic)
- cloudflare/README.md (nothing obtained from anthropic)
- cloudflare/docs/MIGRATION-PLAN.md (nothing obtained from anthropic)
- cloudflare/.gitignore (nothing obtained from anthropic)
- cloudflare/docs/CHANGES.md (nothing obtained from anthropic)
- cloudflare/docs/MIGRATION-REPORT.md (nothing obtained from anthropic)
- cloudflare/frontend/index.html (nothing obtained from anthropic)
- cloudflare/frontend/src/App.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/components/FolderList.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/components/ImageGrid.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/components/UploadButton.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/api.ts (nothing obtained from anthropic)
- cloudflare/frontend/src/main.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/arcblock-did.ts (nothing obtained from anthropic)
- cloudflare/frontend/src/plugins/presigned-upload.ts (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/blocklet-ui-react-dashboard.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/arcblock-ux.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/blocklet-js-sdk.ts (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/blocklet-ui-react.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/blocklet-ui-react-header.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/did-connect-react-button.tsx (nothing obtained from anthropic)
- cloudflare/frontend/tsconfig.json (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/did-connect-react-session.tsx (nothing obtained from anthropic)
- cloudflare/frontend/src/shims/blocklet-ui-react-footer.tsx (nothing obtained from anthropic)
- cloudflare/frontend/vite.config.ts (nothing obtained from anthropic)
- cloudflare/migrations/0001_initial.sql (nothing obtained from anthropic)
- cloudflare/src/tests/utils.test.ts (nothing obtained from anthropic)
- cloudflare/pnpm-lock.yaml (nothing obtained from anthropic)
- cloudflare/scripts/migrate-data.ts (nothing obtained from anthropic)
- cloudflare/src/tests/worker.integration.ts (nothing obtained from anthropic)
- cloudflare/src/db/schema.ts (nothing obtained from anthropic)
- cloudflare/src/routes/cleanup.ts (nothing obtained from anthropic)
- cloudflare/src/middleware/auth.ts (nothing obtained from anthropic)
- cloudflare/src/routes/status.ts (nothing obtained from anthropic)
- cloudflare/src/routes/folders.ts (nothing obtained from anthropic)
- cloudflare/src/routes/serve.ts (nothing obtained from anthropic)
- cloudflare/src/routes/unsplash.ts (nothing obtained from anthropic)
- cloudflare/src/routes/upload.ts (nothing obtained from anthropic)
- cloudflare/src/utils/hash.ts (nothing obtained from anthropic)
- cloudflare/src/types.ts (nothing obtained from anthropic)
- cloudflare/src/utils/s3.ts (nothing obtained from anthropic)
- cloudflare/src/worker.ts (nothing obtained from anthropic)
- cloudflare/wrangler.toml (nothing obtained from anthropic)
- cloudflare/tsconfig.json (nothing obtained from anthropic)
- cloudflare/vitest.config.ts (nothing obtained from anthropic)
- packages/uploader/src/react/plugins/ai-image/show-panel/output/index.tsx (nothing obtained from anthropic)
- packages/uploader/src/react/plugins/presigned-upload.ts (nothing obtained from anthropic)
- packages/uploader/src/react/uploader.tsx (nothing obtained from anthropic)
- pnpm-lock.yaml (nothing obtained from anthropic)
Files not reviewed due to errors (49)
- cloudflare/README.md (no response)
- cloudflare/docs/MIGRATION-PLAN.md (no response)
- cloudflare/drizzle.config.ts (no response)
- cloudflare/docs/MIGRATION-REPORT.md (no response)
- cloudflare/.gitignore (no response)
- cloudflare/docs/CHANGES.md (no response)
- cloudflare/frontend/src/App.tsx (no response)
- cloudflare/frontend/src/api.ts (no response)
- cloudflare/frontend/index.html (no response)
- cloudflare/frontend/src/components/FolderList.tsx (no response)
- cloudflare/frontend/src/components/ImageGrid.tsx (no response)
- cloudflare/frontend/src/components/UploadButton.tsx (no response)
- cloudflare/frontend/src/plugins/presigned-upload.ts (no response)
- cloudflare/frontend/src/shims/arcblock-did.ts (no response)
- cloudflare/frontend/src/main.tsx (no response)
- cloudflare/frontend/src/shims/arcblock-ux.tsx (no response)
- cloudflare/frontend/src/shims/blocklet-js-sdk.ts (no response)
- cloudflare/frontend/src/shims/blocklet-ui-react-dashboard.tsx (no response)
- cloudflare/frontend/src/shims/blocklet-ui-react-header.tsx (no response)
- cloudflare/frontend/src/shims/blocklet-ui-react.tsx (no response)
- cloudflare/frontend/src/shims/did-connect-react-button.tsx (no response)
- cloudflare/frontend/src/shims/blocklet-ui-react-footer.tsx (no response)
- cloudflare/frontend/src/shims/did-connect-react-session.tsx (no response)
- cloudflare/frontend/tsconfig.json (no response)
- cloudflare/frontend/vite.config.ts (no response)
- cloudflare/migrations/0001_initial.sql (no response)
- cloudflare/pnpm-lock.yaml (no response)
- cloudflare/scripts/migrate-data.ts (no response)
- cloudflare/src/tests/utils.test.ts (no response)
- cloudflare/src/tests/worker.integration.ts (no response)
- cloudflare/src/db/schema.ts (no response)
- cloudflare/src/middleware/auth.ts (no response)
- cloudflare/src/routes/cleanup.ts (no response)
- cloudflare/src/routes/folders.ts (no response)
- cloudflare/src/routes/serve.ts (no response)
- cloudflare/src/routes/status.ts (no response)
- cloudflare/src/routes/unsplash.ts (no response)
- cloudflare/src/routes/upload.ts (no response)
- cloudflare/src/types.ts (no response)
- cloudflare/src/utils/hash.ts (no response)
- cloudflare/src/worker.ts (no response)
- cloudflare/src/utils/s3.ts (no response)
- cloudflare/tsconfig.json (no response)
- cloudflare/vitest.config.ts (no response)
- packages/uploader/src/react/plugins/ai-image/show-panel/output/index.tsx (no response)
- cloudflare/wrangler.toml (no response)
- packages/uploader/src/react/plugins/presigned-upload.ts (no response)
- packages/uploader/src/react/uploader.tsx (no response)
- pnpm-lock.yaml (no response)
Review comments generated (0)
- Review: 0
- LGTM: 0
Code improvements:
- Multipart: use R2 binding for create/complete/abort instead of S3 API
(zero latency, no credential dependency, only listParts still uses S3)
- proxy-put: stream request body directly to R2 instead of arrayBuffer()
(avoids 128MB memory ceiling for large files in dev mode)
- Cleanup: delete temp R2 objects for expired single-file sessions
(previously only multipart sessions were cleaned up)
- SVG sanitization: add <style> block stripping and xlink:href data: fix
- D1: add TODO for withSession("first-primary") write consistency
- Fix TypeScript error in direct upload FormData casting
Documentation updates:
- README: fix wrangler.toml line number reference, clarify deploy paths
- MIGRATION-REPORT: Cloudflare Pages → Workers Static Assets
- MIGRATION-PLAN: mark /api/url/import as unimplemented, add GET /api/folders
- All design docs: add "historical reference" note at top
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hub image URLs (hub.aigne.io/image-bin/uploads/...) fail to load directly from the browser due to connection issues. Rewrite URLs in the generation response to go through /api/image/proxy, which fetches from Hub server-side and streams to the client. Only allows proxying URLs from the configured AIGNE_HUB_URL to prevent open proxy abuse. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AI generated images from AIGNE Hub are temporary and should not be cached. Previous 24h browser cache caused stale images to appear when selecting generated results. Also disable CF edge cache for the proxy fetch. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hub image URLs are served directly to the frontend now. The proxy endpoint caused slow loading and stale image issues. The /api/image/proxy endpoint is kept available but not auto-applied — can be used manually if needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AI Image generation: - Download hub images to tmp/ai/ in R2 during generation - Return local /uploads/tmp/ai/xxx.png URLs (fast, no CORS) - Cron cleanup deletes tmp/ai/ files older than 24 hours - User clicks "Use selected" → fetches from local R2 (instant) Toast shim: - Fix default export: Toast object (with success/error methods) was incorrectly exporting ToastProvider as default Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Changed /uploads/:filename to /uploads/* wildcard match so that AI-generated temp images at /uploads/tmp/ai/xxx.png can be served. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ages These packages are pure UI components with no Blocklet Server dependency, so shims were unnecessary. Removed 13 shim files, keeping only 7 shims for packages that truly depend on Blocklet Server runtime: - @blocklet/js-sdk (createAxios) - @blocklet/ui-react (Dashboard/Header/Footer/ComponentInstaller) - @arcblock/did-connect-react (SessionProvider/ConnectButton) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Shims: clarify only @blocklet/* and did-connect-react need shims, @arcblock/ux and @arcblock/did use real packages - Add AIGNE_HUB_URL to secrets documentation - Add AI temp image cleanup (tmp/ai/, 24h) to architecture description - Update environment differences table Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resource tab is a Blocklet Server feature (browse installed component resources) that has no equivalent in CF Workers. Added window.blocklet. inCFWorkers flag to conditionally hide it. Blocklet version unaffected (flag is undefined by default). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updated the PresignedUploadPlugin to construct an absolute upload URL when the URL starts with a slash. This change ensures compatibility with cross-origin requests, particularly when using Cloudflare Workers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Changes
New: cloudflare/ directory (Worker backend + frontend build config)
Modified: packages/uploader/ (backward compatible)
TODO (post-merge)
Test plan
🤖 Generated with Claude Code