Skip to content

Webflow-Examples/fde-page-watcher

Repository files navigation

Page Watch · Brand Studio

Nightly Lighthouse (PageSpeed Insights) and agent-readiness monitoring for a watchlist of priority Webflow.com pages. For each page it tracks per-strategy (mobile + desktop) scores over time, classifies status, surfaces recommendations, lets you triage them into tasks, log change markers, and posts drop alerts and 2/7/30-day follow-up comparisons to Slack.

Built with Next.js (App Router) + React. TypeScript throughout.

Getting started

npm install
npm run dev      # http://localhost:3000  (the bundled launch config uses 3100)

Other scripts:

npm run build    # production build
npm start        # serve the production build
npm run lint     # eslint
npm test         # vitest (unit + integration-focused concurrency tests)
npm run collector:check    # type-check the durable Workflow worker
npm run collector:dry-run  # bundle/validate the Workflow without deploying

Environment

All are optional for local development — the app runs without them.

Variable Purpose
PAGESPEED_API_KEY PSI credential. Configure it on the collector Worker; it is also used by the local runner.
CRON_SECRET Shared bearer secret for nightly requests, Workflow dispatch, and collector callbacks.
COLLECTOR_URL Production Workflow endpoint, ending in /jobs.
COLLECTOR_CALLBACK_URL Optional direct app Worker override. By default callbacks use Webflow's automatic ASSETS_PREFIX.
COLLECTOR_SECRET Optional separate dispatch credential; defaults to CRON_SECRET.
DATASET_MODE demo uses the existing sample namespace; live uses an isolated, initially empty namespace.
BASE_URL Webflow Cloud mount path (for example /page-watch); client routes and APIs are prefixed automatically.
SLACK_WEBHOOK_URL Incoming webhook for drop alerts and follow-up reports.
PSI_MOCK Local-only deterministic scores instead of PSI.
PSI_RUNS Samples per strategy (1–5, default 5).
ANTHROPIC_API_KEY Enables post-commit recommendation explanations and Watcher narratives on the app.
ANTHROPIC_MOCK Uses deterministic placeholder AI text without making Anthropic requests.

Put these in .env.local.

How it works

  • Collection — baseline, on-demand, and nightly actions first reserve a durable D1 job and return 202. In production a Cloudflare Workflow performs up to five PSI samples per strategy, uploads the raw JSON to R2, scans agent readiness, and calls the app back with a versioned result. Retries are durable, duplicates coalesce, stale jobs become visible failures, and a run ID can append history only once.
  • Baselines — ordinary on-demand/nightly runs may store snapshots, history, recommendations, and scan results, but a page stays Pending until the user explicitly captures a baseline. Zero placeholders are never treated or shown as real baselines.
  • Nightly job — wire a scheduled job to POST /api/cron/nightly. It priority-sorts the watchlist and dispatches Workflows; it does not hold a Webflow request open while PSI runs. CRON_SECRET is mandatory.
  • Storage — a tenant-scoped DataStore (see src/lib/store) mirrors the state snapshot, append-only history/markers, and raw report tiers. Local development uses the filesystem under .data/, with an in-memory fallback for read-only hosts and per-tenant serialized atomic replacement. A deployed OpenNext worker with DB and REPORTS bindings automatically uses D1 plus R2; D1 state updates use version-guarded compare-and-swap retries.
  • State mutations go through targeted server-side domain endpoints (/api/pages, /api/recs, /api/pages/[id]/*) and the store-level atomic update primitive. External PSI/Slack work happens outside that critical section; result commits re-read authoritative state.
  • Background execution — Cloudflare Workflows own production execution. The local runner uses Next.js after() only for development.
  • Post-commit enrichment — after the scores/raw reports are safely stored, the Workflow separately retries Anthropic recommendation explanations, Watcher narrative refreshes, Slack alerts, and due follow-ups. Optional integrations cannot roll back or mislabel a successful collection.

Production setup

The interactive app relies on the enclosing site's SSO. There is no second HTTP Basic layer and no FDE_ACCESS_* configuration. Non-interactive nightly and collector callback endpoints remain protected by CRON_SECRET.

  1. Confirm the app has the DB and REPORTS declarations from wrangler.json. Webflow Cloud applies 0003_collection_jobs.sql during the GitHub-driven deployment. Production intentionally fails instead of falling back to process memory when either binding is absent.
  2. Deploy collector-worker/wrangler.jsonc. Configure its PAGESPEED_API_KEY and CRON_SECRET secrets.
  3. Set COLLECTOR_URL, CRON_SECRET, and DATASET_MODE on the Webflow app. BASE_URL and ASSETS_PREFIX are supplied automatically by Webflow Cloud; the latter is the direct Worker origin used for SSO-independent callbacks.
  4. Call /api/health after deployment. It returns 503 if durable storage or the production collector is missing, without exposing secret values.

Use DATASET_MODE=demo for the existing sample state and DATASET_MODE=live for real URLs. The two modes use separate tenant keys in the same D1 database, so switching modes is reversible and never overwrites the demo dataset.

Deferred integrations

  • Per-user identity and role-based authorization
  • Automated page remediation

Product decisions

The four fixed scoring/scheduling choices for this phase are documented in DECISIONS.md.

About

Next.js page watcher app

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors