Weekly site performance
September 9, 2026 ยท View on GitHub
Production landing performance is measured every Monday (UTC) against https://kody.codes/. The collector only answers one question: did something cross a budget or fail a landing signal?
| Verdict | What happens |
|---|---|
ok | Budgets hold. Existing "Weekly site perf" issues close. No package invoke. |
needs-fix | A tracking issue stays open and the workflow invokes Kent's weekly-site-perf Kody package. That package launches a Cursor cloud agent. The agent decides whether to implement a fix or stop for a human. |
The GitHub Action never edits the site and never classifies "human vs implementable." It measures, upserts the issue, and (when a fix is needed) calls Kody.
Measure
npm run site-perf -- --url https://kody.codes/ --json
tools/site-perf/collect.ts fetches the
homepage, records HTML weight, Cache-Control, the largest same-origin JS
payload, the preloaded LCP image, TTFB, and Server-Timing phases (session,
ssr, plus loader phases such as listings). When the primary URL is /, it
also probes /onboarding and /docs/how-kody-works for the same timing
snapshot. Those extra pages are observational and do not change the verdict. A
failed extra probe is omitted so homepage classify still runs. Homepage HTML
that lacks an app ssr phase is a finding. A syntax-highlight modulepreload
on / is a finding (Shiki belongs on guides and onboarding, not the landing
entry). The collector then classifies against
tools/site-perf/budget.json.
.github/workflows/weekly-site-perf.yml
runs that collector on Mondays at 14:17 UTC and on workflow_dispatch.
needs-fix upserts Weekly site perf: needs a fix. A later ok run closes
that issue (and the older actionable / human review titles).
Kody package invoke
When the verdict is needs-fix and KODY_WEBHOOK_URL_RUN is set, the same job
POSTs that minted webhook URL with a params-mode JSON body and an
Idempotency-Key header. There is no Authorization header; the URL is the
credential. See inbound webhooks.
The weekly-site-perf package owns the agent prompt and calls createAgent
from @kentcdodds/cursor. The Cursor API key stays a Kody secret on that Cursor
package. The agent implements an obvious local fix when it can, follows
.agents/skills/ship-pr/SKILL.md, or
leaves the tracking issue open when a human should decide.
@kentcdodds/weekly-site-perf declares webhook run (inputMode: "params",
responseMode: "sync") on the root . export. The live Action reads the minted
URL from the repository (or org) secret KODY_WEBHOOK_URL_RUN. Kent copies that
value from the Kody user secret weeklySitePerfWebhookRun at
https://kody.codes/account/secrets/user/weeklySitePerfWebhookRun. Agents never
paste the URL. Rotate with webhookUrlRotate, then update both the Kody user
secret and the GitHub secret. See setup manifest.
If the secret is unset, blank, or not a valid http(s) URL, the workflow still
measures and upserts the issue. It skips the invoke so the weekly job stays
green.
Retries of the same GitHub run reuse
Idempotency-Key: weekly-site-perf:<GITHUB_RUN_ID> (and the same
idempotencyKey in the JSON body). A successful sync invoke that returns an
agent URL comments it on the open needs-fix issue. 409 invocation_in_progress
counts as launched; 409 idempotency_mismatch and other non-2xx responses fail
the step.
What the homepage already does
Anonymous /, /pricing, /blog, /community, /onboarding, /docs, and
/docs/:slug HTML is public, max-age=60, stale-while-revalidate=300 with
Vary: Cookie. Anonymous /onboarding.json uses the same cache with
Vary: Cookie. Doc JSON (/docs/:slug.json) is shared publicly without a
cookie vary because the body is the same for every visitor. Any kody_session
cookie, a resolved session, or a Set-Cookie response stays no-store on HTML.
Auth, OAuth, and account pages never use the short CDN cache.
Landing layout CSS lives in packages/worker/public/styles.css (.landing-*)
so SSR does not emit a Remix style tag per marketing node. Hero and below-fold
art ship srcset variants. Login, signup, and verify load the Turnstile widget
immediately.
Budget
Edit tools/site-perf/budget.json when the
live site has a new honest baseline. Bump a threshold only after the change is
on production and the collector agrees.
htmlBytes counts the full anonymous document, including the intentionally
inlined styles.css <style> block (see
inline-stylesheet.ts).
That trade removes a render-blocking stylesheet round trip; do not "fix" an
html-over-budget finding by switching back to a <link rel="stylesheet">
without a product call. When landing CSS or below-fold marketing markup grows
for real product work (hero agents, testimonials, factory loop, and so on),
raise htmlBytes to the new honest production size instead of cutting the page.