BulkFlow is a private, Google-authenticated CSV processing application deployed as one Cloudflare Worker at:
The React frontend, API, background queue consumer, and live WebSocket endpoint are built and deployed together from frontend/.
- Replaced the Vercel frontend and Render backend with one Cloudflare deployment.
- Replaced Redis/BullMQ with Cloudflare Queues.
- Replaced MongoDB runtime storage with Cloudflare D1.
- Replaced temporary server files with streamed Cloudflare R2 objects.
- Replaced Socket.IO with a hibernating Durable Object WebSocket.
- Removed email entry, password flows, OTP, SMTP, and completion emails.
- Added Google Identity Services as the only sign-in method.
- Added private per-user history, live progress, validation errors, and infinite record browsing.
- The browser creates an authenticated upload tracker in D1.
- The browser streams the raw CSV through the Worker into R2, with upload progress visible locally.
- The Worker publishes one small job to Cloudflare Queues.
- The queue consumer streams and parses the R2 object, writing compact 75-row JSON chunks to D1.
- A hibernating Durable Object broadcasts live progress to the authenticated browser.
- The source object is deleted from R2 after successful processing. The processed result remains in D1.
This design uses no Redis server, MongoDB connection, SMTP server, or permanently running process.
The production resources are already created and bound in frontend/wrangler.jsonc:
| Binding | Resource | Purpose |
|---|---|---|
DB |
D1 bulkflow-db |
Users, upload metadata, errors, and processed row chunks |
UPLOADS |
R2 bulkflow-uploads |
Temporary source CSV storage |
UPLOAD_QUEUE |
Queue bulkflow-jobs |
Background CSV processing |
PROGRESS_ROOMS |
Durable Object ProgressRoom |
Live progress WebSockets |
The queue is configured for one job per consumer invocation, up to two concurrent jobs, and automatic retries using the Free plan's platform execution limits.
frontend/.env.production:
VITE_GOOGLE_CLIENT_ID=your-web-client-id.apps.googleusercontent.comThis value is public by design and is embedded into the browser bundle.
Store these in Cloudflare, never in Git:
npx wrangler secret put GOOGLE_CLIENT_ID
npx wrangler secret put SESSION_SECRETGOOGLE_CLIENT_ID must exactly match VITE_GOOGLE_CLIENT_ID. SESSION_SECRET should be at least 32 random bytes. Both production secrets are installed during deployment.
For local development, copy frontend/.dev.vars.example to frontend/.dev.vars and fill both values. Copy frontend/.env.example to frontend/.env.local for the browser-side client ID.
No Google client secret is used. If one was shared in chat or elsewhere, rotate it in Google Cloud because it is unnecessary for this flow.
In Google Cloud Console, open the Web OAuth client and add these Authorized JavaScript origins:
http://localhost:5173
https://bulkflow.suryansh.lol
No redirect URI is required because the app verifies the Google ID token on the Worker.
Use Node.js 22.19 or newer.
cd frontend
npm ci
npm run db:migrate:local
npm run devOpen http://localhost:5173.
cd frontend
npm test
npm run build
npx wrangler deploy --dry-run
npm run db:migrate:remote
npm run deployThe custom domain is declared in wrangler.jsonc, so Wrangler manages the Worker custom-domain binding for bulkflow.suryansh.lol.
- Accepted format: UTF-8 CSV.
- Maximum source file size: 95 MB, below Cloudflare's 100 MB Free-plan request ceiling.
- Quoted commas, escaped quotes, CRLF, and multiline quoted fields are supported.
- Blank header names are normalized and duplicate headers receive numeric suffixes.
- Rows with a different column count are reported and skipped.
- Up to the first 100 row errors are retained for display.
- Excel files must be exported to CSV. The previous backend advertised
.xlsxbut only parsed CSV.
Cloudflare's Free plan has usage ceilings rather than a Vercel-style expiring deployment. Current major allowances include 100,000 Worker requests/day, 10,000 Queue operations/day, 100,000 D1 rows written/day, 5 million D1 rows read/day, and 10 GB-month of R2 Standard storage. If a daily ceiling is reached, service for that product resumes when the allowance resets.
- Google ID tokens are verified against Google's JWKS, issuer, audience, and verified-email claim.
- Sessions are signed, one-hour, HTTP-only,
SameSite=Laxcookies. - Google login uses double-submit CSRF protection.
- Every upload, WebSocket, history query, result page, and deletion is ownership-checked.
- State-changing API requests reject foreign origins.
- Source files are private R2 objects and are deleted after successful processing.
- Secrets and local Cloudflare state are ignored by Git.
Atlas database-user credentials can create a logical database inside an existing cluster, but they cannot create a new Atlas cluster. Creating a cluster requires Atlas account access or an Atlas Administration API service account. A separate bulkflow logical database was initialized in the provided existing cluster as requested. BulkFlow production intentionally uses D1, so the Worker does not need a MongoDB runtime connection or another paid/always-on service.