Cloudflare Pages does not support scheduled tasks. This project requires hourly syncing, so it uses Cloudflare Workers.
To maintain backwards compatibility, configure the old Pages deployments to redirect to Workers.
Create _redirects file in the Pages project root:
/api/* https://validators-api-main.je-cf9.workers.dev/api/:splat 301
/* https://validators-api-main.je-cf9.workers.dev/:splat 301
Deploy this file to validators-api-mainnet Pages project.
Create _redirects file in the Pages project root:
/api/* https://validators-api-test.je-cf9.workers.dev/api/:splat 301
/* https://validators-api-test.je-cf9.workers.dev/:splat 301
Deploy this file to validators-api-testnet Pages project.
Go to Cloudflare Dashboard → Pages → [Project] → Rules → Redirects:
Mainnet:
- Source:
/*→ Destination:https://validators-api-main.je-cf9.workers.dev/$1(301)
Testnet:
- Source:
/*→ Destination:https://validators-api-test.je-cf9.workers.dev/$1(301)
Test redirects work:
curl -I https://validators-api-mainnet.pages.dev/api/v1/status
# Should return 301 redirect to validators-api-main.je-cf9.workers.dev
curl -I https://validators-api-testnet.pages.dev/api/v1/status
# Should return 301 redirect to validators-api-test.je-cf9.workers.dev- Verify Workers fully operational
- Deploy redirects to Pages projects
- Monitor for 1-2 weeks
- (Optional) Deprecate legacy
.pages.devURLs and add a custom domain
This implementation does not perform any remote migration or deployment. Run each remote command manually, testnet first, after reviewing its target.
-
Authenticate Wrangler and confirm the expected account:
pnpm exec wrangler login pnpm exec wrangler whoami
-
Inspect applied migrations and relevant table/index definitions. Never assume a migration is already applied:
pnpm exec wrangler d1 execute validators-api-testnet --remote --env testnet --command "SELECT id, name, applied_at FROM _hub_migrations ORDER BY id;" pnpm exec wrangler d1 execute validators-api-testnet --remote --env testnet --command "SELECT name, type, sql FROM sqlite_schema WHERE name IN ('_hub_migrations', 'activities', 'activity_epochs', 'scores', 'validators') OR name LIKE 'idx_%' ORDER BY type, name;"
-
Export a backup outside this repository:
pnpm exec wrangler d1 export validators-api-testnet --remote --env testnet --output ../validators-api-testnet-before-score-v2.sql
-
Put migration-only D1 HTTP credentials in
.env.testnet:NUXT_HUB_CLOUDFLARE_ACCOUNT_ID=... NUXT_HUB_CLOUDFLARE_DATABASE_ID=... NUXT_HUB_CLOUDFLARE_API_TOKEN=...
Keep these values out of deployed runtime variables. Migration scripts enable the HTTP driver only for their own command and fail if any credential is missing.
Repeat inspection and backup with validators-api-mainnet and without --env testnet only after testnet validation passes.
-
Keep testnet
NUXT_SCORE_V2_MODE=off. -
Apply all pending tracked migrations:
pnpm db:migrate:testnet
This uses NuxtHub's basename-compatible
_hub_migrationsledger. Do not substitutewrangler d1 migrations apply; Wrangler records full filenames and can replay an existing NuxtHub baseline. -
Inspect
_hub_migrationsand relevant schemas again. -
Build and deploy testnet while v2 remains off:
CLOUDFLARE_ENV=testnet pnpm build pnpm exec wrangler --cwd .output deployNuxtHub selects the testnet bindings during the build. Rebuild after each
NUXT_SCORE_V2_MODEchange; deploy the matching.outputwithout--env. -
Let the hourly job discover epochs, repair recent activity, store the snapshot, then calculate v1 scores.
-
Set
NUXT_SCORE_V2_MODE=shadow, deploy, and validate v1/v2 rows, activity coverage, score versions, andcurrent,stale, orno_scoreAPI states. -
Set
NUXT_SCORE_V2_MODE=activeonly after shadow results pass. -
Repeat the same inspect, backup, migrate, off, repair, shadow, validate, and active sequence for mainnet. Build mainnet with
pnpm buildand deploy withpnpm exec wrangler --cwd .output deployafter each mode change.
Activity marker interpretation during validation:
syncing: repair attempt is inside its six-hour lease.complete: storedfinalizedmarker has an exact elected set and matching counts.incomplete: expected activity has no valid finalized marker.failed: attempt rolled back and recorded an error for retry.
API list, detail, and status endpoints accept score-version=1|2. Omitted version follows rollout mode: off and shadow select v1; active selects v2. Selected-version rows are filtered before latest-score selection. current means latest completed epoch is covered, stale preserves an older valid score, and no_score returns null score values.
Set NUXT_SCORE_V2_MODE=off, deploy the configuration change, and request score-version=1 explicitly while caches settle. Keep both v1 and v2 rows intact. Do not roll back schema or score data destructively.