Decision and current state
Gradually adopt Oxlint and Oxfmt over Biome, and move application hosting toward Cloudflare. These are independent changes: Oxc can lint and format Next.js source without changing its runtime. Vite+ consolidates tooling; it does not translate Next.js routes, server components, or server actions. The foundation adds root-pinned Oxlint/Oxfmt, shared configuration and explicit-file commands. Existing Biome scripts, CI, editor defaults, import organization and release/generated-file formatting remain authoritative. No workspace has completed the switch merely because these tools are installed. Lettin and Parley already have Next.js/OpenNext Worker deployments. Their next architecture milestone is a Vite-native runtime preserving existing contracts. React Router Framework Mode with the Cloudflare Vite plugin is a candidate requiring a scoped compatibility proof. The retainedapps/tanstack-web remains paused.
Platform-wide target and daily checkpoints
The ultimate target is every active application using Vite+, hosted on Cloudflare, with Oxc linting/formatting. Work proceeds incrementally alongside the product backlog; the initial Worker inventory below is the first wave, not a limit on the program. Retained paused applications remain excluded until resumed. Mobile continues to use its native Flutter toolchain; shared services and web surfaces follow the platform target without implying a rewrite of native UI. Keep per-app ownership, prerequisites and exact-head receipts in the private request backlog and coordination board. Checkpoint reviewable PRs as each unit finishes. Separate implemented, CI-verified, runtime-accepted and production-delivered states. A merge does not establish hosting cutover. Capture new Worker/app scope and compatibility findings before dispatching the next unit; avoid competing migration and product owners in the same files.Complete Worker migration scope
The migration includes every active Worker-backed app/service, not only Lettin and Parley. Framework replacement applies to Next/OpenNext web apps; native Workers retain their fetch/email/scheduled/RPC entrypoints while adopting Vite+ and Oxc tooling. A backend service does not need React or a router to qualify.
This inventory follows active checked-in Wrangler configurations. Existing
apps/backend and apps/tanstack-web Wrangler files are retained paused artifacts,
not migration targets. New active Worker configurations must join the inventory.
Deployment existence and canonical health still require live evidence.
Begin with the portable session core and the already Vite-native Colab toolchain,
then use the same verified conventions for native service workers. Meet, Parley
and Lettin require the shared framework-adapter work before full web replacement.
Each app retains its own exact-commit test/type/lint/build and Worker acceptance
receipts; one green app cannot establish another app’s readiness.
cf CLI adoption alongside Vite+
Prefer Cloudflare’s cf CLI over Wrangler as each operation proves compatible. This is a phased tooling decision, separate from framework migration and production promotion. Existing Wrangler commands/configurations remain authoritative until that scope passes its replacement gates. Cloudflare’s launch announcement introduces cf in open beta, with JSON output and a generated API command surface. Vite-built Workers can migrate to typedcloudflare.config.ts; configuration uses
Vite modes, whose semantics differ from Wrangler environments. cf still delegates
some development/deployment paths to Wrangler. Recheck upstream support before
implementing a scope; the announcement is not evidence of repository compatibility.
- Read-only discovery first. Pin a reviewed cf version through the owning workspace’s package manager. Verify help/schema, authentication and selected account independently; existing Wrangler login does not establish cf access. Exercise bounded inventory/observability queries and record supported command mappings. Filter JSON to required fields and keep raw logs/credentials private.
- Pilot a Vite-native Worker. Coordination or Colab is a candidate after its Vite+ artifact gates pass. Review migration output in an isolated worktree; do not run a repository-wide migrator. Verify compatibility with the pinned Vite+ core, Cloudflare plugin and test runner before adopting typed configuration.
- Prove configuration and artifact parity. Compare resolved settings for every used mode: account/name, routes/domains, compatibility date/flags, assets, service bindings, Durable Object names/classes/migrations, storage identifiers, triggers, secrets and observability. Preserve resource identity; never infer that a similarly named mode selects the same deployed environment. Select one authoritative configuration per scope, with an explicit fallback procedure.
- Replace operations separately. Map local development, type generation, tests, CI bundling, validation upload, tail, version inspection, deployment and rollback individually. Unsupported or unverified operations retain Wrangler. CI must exercise the final emitted artifact and preserve exact-SHA and target identity checks; a CLI rename or dry run alone cannot establish runtime health.
- Roll out per owner. Update scripts, workflow permissions, runbooks and skill references together after focused tests and exact-commit CI pass. Production commands change only with separately authorized promotion, bounded scope and verified rollback. Keep paused runtimes excluded.
Use the tooling foundation
From the repository root, pass explicit files you own:oxc:write explicitly
applies formatting. The wrapper rejects empty selections, flags, globs, directories,
symlinks resolving outside the permitted source, build/dependency trees and paused
runtimes. Installed tools run with two threads, without Turbo or builds. Tests cover
scope rejection, native-dialog linting, read-only formatting and idempotence.
The baseline uses correctness rules, native-dialog prohibition, TypeScript/React/
accessibility plugins, and two-space, 80-column, single-quote, semicolon, LF,
ES5-trailing-comma formatting. This is not Biome rule parity. Manifest sorting
is disabled; import and Tailwind sorting are not enabled.
Move one workspace at a time
- Inventory Biome rules/suppressions, file types, editors, Turbo/CI tasks and generated-file producers. Compare read-only Oxc output on owned files.
- Map rules by behavior, including accessibility, hooks, unused imports and intentional exceptions. Record gaps and compensating validators; preserve CSS/Tailwind validation and import organization.
- Isolate formatting from product logic. Preserve generated/vendor ownership; translate suppressions only when their semantics match.
- Select one formatter per migrated scope and update CI, editors, generators and docs together. Require applicable exact-commit test/type/lint/build evidence.
- Remove Biome only once every remaining scope and release tool has equivalent coverage. Preserve auth, i18n, source-size, import-boundary and runtime guards.
First-party portability contract
Maintain domain rules and application services as ordinary TypeScript modules. Reusable React components may depend on React and framework-independent UI primitives; they receive navigation, translated labels and data through typed props or a small explicitly scoped provider. React Server Components are an optional adapter surface, never a prerequisite for consuming the domain package.
Prefer existing first-party packages and narrow public subpath exports over a new
universal framework wrapper. Keep Next-specific compatibility entrypoints stable
while adding portable ones. Do not call an entire package framework-agnostic just
because one file is pure: consumers must resolve its entrypoint without transitively
loading Next/OpenNext or Cloudflare. Validate import graphs and consumer builds in
CI. Runtime-specific optional adapters must have explicit entrypoints/dependencies.
Use standard
Request, Response, Headers, URLs and AbortSignal at HTTP
boundaries where appropriate. Pass request context per invocation; never store
actors or bindings in process-wide mutable state. Inject verified identity rather
than accepting browser-provided user IDs as authority. Preserve audience, expiry,
MFA, consent, membership and revocation checks in reusable policy services.
Current seams include Lettin’s Actor/Store context and SQL permission fences,
with bindings/identity/HTTP as framework adapters. Parley/Meet domain contracts can
remain shared while routes, session lookup and meeting UI adapters are extracted.
A package can support Next.js, React Router or other React hosts by implementing
these small adapters; support for every framework is a goal requiring consumer
verification, not an automatic guarantee.
Vite-native Worker acceptance gates
Prove a small authenticated vertical slice before replacing the complete app.
Document fixture boundaries and hosted dependencies: local Durable Objects do not
validate Cloudflare SFU/TURN. Hosting adoption does not imply migrating every store
to D1 or replacing Supabase. Database changes, schedules, secrets and canonical
traffic each need a bounded plan. Pin the promotion range, retain a rollback
artifact and verify schema/binding compatibility and health before promotion.
Runaway-work and cost acceptance
Every migration or change that adds or amplifies billable work must include a cost-safety review. The reported runaway Durable Object alarm incident is a warning about self-sustaining work, not an independently verified account of provider usage. Do not rely on future refunds, billing notifications or a per-invocation CPU limit to cap total storage, requests, retries or downstream spend. Durable Object alarms are at-least-once and automatically retry thrown errors. Explicit rescheduling can create another chain beyond those retries. Ingress rate limits cannot stop work that an alarm, queue consumer or cron trigger already owns.
Require regressions for empty queues, expired state, duplicate execution, restart,
clock/deadline boundaries, persistent downstream failure, no progress and stop-versus-
reschedule races. Count storage/downstream calls as well as final return values;
prove bounds under repeated wakes in isolated fixtures and the real local Worker.
Exact-commit CI must exercise the emitted artifact. Keep live account settings,
alert delivery and hosted shutdown verification as separate production evidence.
CPU limits constrain an invocation, not the number of invocations or all billable
services. Usage notifications are detection, not an automatic spending cutoff.
Choose service-specific limits with measured workloads; do not silently apply an
arbitrary global value that breaks realtime or recovery behavior. See current
Workers pricing and custom CPU limits
and available billing alerts.
Any automatic circuit breaker must itself perform bounded work and fail safely
without deleting original data or retrying indefinitely.
Existing tests and code must be inspected per service; this foundation establishes
review gates and does not assert that every deployed alarm is protected or that
account alerts are configured.