Problem
Uptimer currently deploys two Cloudflare applications: a Worker for the API/scheduled monitor engine and a Pages project for the React UI. This works, but it makes self-hosting and fork-based updates more complicated than necessary:
- Users need both Workers and Pages permissions in their Cloudflare API token.
- The GitHub Actions workflow has to create/deploy two resources and pass the Worker origin into the Pages build/runtime.
- The deployed product has two default hostnames (
*.workers.dev and *.pages.dev) unless the user adds custom routing.
- Same-origin deployment would simplify API configuration and reduce the number of moving parts.
Proposed Solution
Add support for deploying the Vite frontend as Cloudflare Workers Static Assets on the same Worker that already serves the API and scheduled handler.
A possible shape:
[assets]
directory = "../web/dist"
binding = "ASSETS"
not_found_handling = "single-page-application"
run_worker_first = ["/api/*"]
Then keep the existing Worker behavior for /api/*, scheduled(), D1, and internal service-binding paths, while static assets and SPA routes are served by the Worker assets layer.
This would allow a single Cloudflare deployment to provide:
- Status page:
https://<worker>.workers.dev/
- Admin dashboard:
https://<worker>.workers.dev/admin
- API:
https://<worker>.workers.dev/api/v1/...
- Cron/scheduled monitoring in the same Worker
Alternatives Considered
Keep the current Pages + Worker architecture as the default, but add an optional single-worker deployment mode in the GitHub Actions workflow. That would preserve backwards compatibility for existing users while giving new self-hosters a simpler path.
Another option is to fully migrate the Pages _worker.js HTML preload/meta injection logic into the Worker. However, that may increase Worker invocations and CPU pressure. A lower-risk first step would be to serve static Vite output from Workers assets and rely on the existing /api/v1/public/homepage bootstrap from the frontend.
Additional Context
Cloudflare Workers now supports deploying static assets and Worker code together. This project already has a mostly same-origin-friendly frontend API client (/api/v1 by default), so the migration looks feasible without changing the product model.
Relevant Cloudflare docs:
Problem
Uptimer currently deploys two Cloudflare applications: a Worker for the API/scheduled monitor engine and a Pages project for the React UI. This works, but it makes self-hosting and fork-based updates more complicated than necessary:
*.workers.devand*.pages.dev) unless the user adds custom routing.Proposed Solution
Add support for deploying the Vite frontend as Cloudflare Workers Static Assets on the same Worker that already serves the API and scheduled handler.
A possible shape:
Then keep the existing Worker behavior for
/api/*,scheduled(), D1, and internal service-binding paths, while static assets and SPA routes are served by the Worker assets layer.This would allow a single Cloudflare deployment to provide:
https://<worker>.workers.dev/https://<worker>.workers.dev/adminhttps://<worker>.workers.dev/api/v1/...Alternatives Considered
Keep the current Pages + Worker architecture as the default, but add an optional
single-workerdeployment mode in the GitHub Actions workflow. That would preserve backwards compatibility for existing users while giving new self-hosters a simpler path.Another option is to fully migrate the Pages
_worker.jsHTML preload/meta injection logic into the Worker. However, that may increase Worker invocations and CPU pressure. A lower-risk first step would be to serve static Vite output from Workers assets and rely on the existing/api/v1/public/homepagebootstrap from the frontend.Additional Context
Cloudflare Workers now supports deploying static assets and Worker code together. This project already has a mostly same-origin-friendly frontend API client (
/api/v1by default), so the migration looks feasible without changing the product model.Relevant Cloudflare docs: