2026 OpenClaw Frontend Practice on a Remote Mac:
Preview Deploy Webhook, Lighthouse CLI, Threshold JSON, Exit Codes, and PR Summaries
Audience: teams running an OpenClaw gateway on a leased remote Mac who want a single reproducible chain from preview webhooks to Lighthouse CLI, threshold JSON, exit codes, and Markdown for GitHub. Slug: 2026-openclaw-remote-mac-preview-lighthouse-webhook.html. See also Deployments + Lighthouse and Vercel deploy-hook smoke.
Deploy webhooks carry preview_url and commit metadata. Linux CI misses Apple compositing and the Safari / WebKit path your users hit. An OpenClaw gateway on a remote Mac verifies signatures, normalizes payloads, runs Lighthouse CLI, compares lhr.json to threshold JSON, maps regressions to exit 2 and infra faults to exit 3, then emits a PR-readable summary.
Outcome. One HTTPS hook, artifacts under .openclaw/reports/, and a short Markdown block you can POST to the PR or deployment row.
Pain points this design removes
- Unauthenticated hooks. Raw
curlfrom CI straight into a shell invites replay attacks and impossible auditing. - Console-only URLs. If the verdict never reaches GitHub, reviewers ship while Lighthouse failures live only in terminal scrollback.
- Flaky comparisons. Without pinned Chromium, warm-up, and JSON thresholds, numeric gates oscillate and teach teams to ignore alerts.
01 Why the OpenClaw gateway should receive the deploy hook
OpenClaw terminates TLS, enforces HMAC or mTLS, rate-limits clients, and emits NDJSON. When Pages, Netlify, Vercel, or your CI fires a deployment webhook, verify the signature here, dedupe with Idempotency-Key, then fork Lighthouse on the Mac so GitHub tokens stay off the edge. Reuse the same ingress for predeploy Lighthouse or build summaries.
After Chromium Lighthouse, add a short Safari / WebKit smoke on the same host so native engine signal sits beside lab scores; optional separate exit code if WebKit should not block merge.
02 Ingress decision matrix
| Approach | Strength | Tradeoff |
|---|---|---|
| OpenClaw gateway webhook | Central signature verification, payload normalization, shared dedupe, Apple hardware next hop. | You must operate TLS certificates and backoff policies yourself. |
GitHub repository_dispatch only |
Built-in audit trail inside GitHub. | Harder to stream warm-up traces to Mac-local NDJSON without cloning tokens into Actions. |
03 Reproducible HowTo steps
- Publish the hook. POST JSON to your OpenClaw HTTPS route with HMAC; reject stale timestamps.
- Normalize fields. Map provider fields to
PREVIEW_URL, captureGIT_SHA,PR_NUMBER, mintOPENCLAW_RUN_ID. - Enqueue on the Mac. Drop a job under
.openclaw/queue/; let launchd or a watcher run it so SSH blips do not lose work. - Warm the preview. Two GETs for HTML and main JS with Lighthouse’s user agent; backoff on
429. - Run Lighthouse CLI.
pnpm exec lighthouse "$PREVIEW_URL" --only-categories=performance --output=json --output-path=".openclaw/reports/${OPENCLAW_RUN_ID}.lhr.json" --chrome-flags="--headless=new"; pin Chrome per branch. - Evaluate thresholds. Read
perf/thresholds.jsonat the same commit; writeverdict.json. - Exit codes.
0pass,2regression,3infra after one retry. - Post the digest. Fill the template below, POST to the PR or deployment API, append NDJSON
phase=preview_lighthouse.
# Minimal gateway guard before forking the worker
set -euo pipefail
test -n "${PREVIEW_URL:-}" && test -n "${GIT_SHA:-}" || exit 3
# openclaw-hook-verify --secret "$HOOK_SECRET" --body "$RAW_BODY" --sig "$SIG_HEADER" || exit 3
04 Threshold table, JSON, and exit codes
| Metric | Example budget | Fail action |
|---|---|---|
| Performance score | >= 0.85 on mobile preset |
Exit 2; include delta versus baseline artifact. |
| LCP / CLS / TBT | LCP <= 2500 ms, CLS <= 0.08, TBT <= 200 ms |
Exit 2; cite worst metric first. |
| Navigation timeout | maxWaitForLoad <= 45000 |
Retry once then exit 3 so merges distinguish infra from regressions. |
{
"performance": { "minScore": 0.85 },
"metrics": {
"largest-contentful-paint": { "maxNumericValue": 2500 },
"cumulative-layout-shift": { "maxNumericValue": 0.08 },
"total-blocking-time": { "maxNumericValue": 200 }
}
}
Exit 0 all budgets met. Exit 2 regression—block merge. Exit 3 infra or auth—retry ops.
05 PR-readable summary template
Stay under ~4 KB for GitHub mobile. Mirror the same text on deployment status when using Deployments API wiring.
### OpenClaw · Lighthouse preview gate
- **Run** `OPENCLAW_RUN_ID` @ `GIT_SHA` on remote Mac (Chromium pinned)
- **URL** `PREVIEW_URL`
- **Scores** perf **{{score}}** (Δ {{delta}} vs baseline)
- **Metrics** LCP **{{lcp}}ms**, CLS **{{cls}}**, TBT **{{tbt}}ms**
- **Verdict** {{pass_or_fail}} — logs `.openclaw/reports/{{run}}.lhr.json`
Pin Chromium weekly; store lhr.json as .openclaw/reports/${OPENCLAW_RUN_ID}.lhr.json; append one-line WebKit smoke status in the PR footer.
06 FAQ: 403, timeouts, duplicate hooks
Why does Lighthouse see HTTP 403 on the preview?
Deploy protection, bots, or missing Authorization block headless Chrome. Reuse headers from deploy-hook smoke, allowlist the Mac IP, or pass short-lived tokens via env—not the PR body.
How do I stop flaky timeouts from blocking merges?
Retry once, bump --max-wait-for-load slightly, then exit 3 so infra owns the incident.
What if the provider sends duplicate webhooks?
Require Idempotency-Key: ${GIT_SHA}:${OPENCLAW_RUN_ID}:lighthouse and skip if the queue entry exists so duplicate hooks do not double-run Lighthouse.
Rent the Same Apple Silicon Your Gates Run On
Open the home page, read help for SSH and VNC basics, compare pricing, and purchase or rent a remote Mac without signing in. Return to the blog index for more OpenClaw playbooks.