Skip to content

fix(registry): return 404 for missing skill pages - #317

Merged
harlan-zw merged 4 commits into
mainfrom
fix/soft-404-missing-skills
Sep 30, 2026
Merged

harlan-zw merged 4 commits into
mainfrom
fix/soft-404-missing-skills

Conversation

@harlan-zw

@harlan-zw harlan-zw commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

❓ Type of change

  • 🐞 Bug fix

📚 Description

Search Console (2026-09-30) lists 2,621 soft 404 pages. Any made-up /gh/<owner>/<repo>/<skill> URL answered 200 with a thin page, noindex, and a canonical to the homepage. The URL space is unbounded, so it also wastes a small crawl budget. The page already said "Skill not found"; only the status and canonical were wrong.

A pure resolveSkillPageState (_tag union) now decides status, robots, and canonical, and SkillDetail.vue applies it during SSR.

State Status Robots Canonical
In registry, indexable 200 index,follow self
In registry, not indexable 200 noindex,follow self
Weaker duplicate 200 noindex,follow the stronger Skill
Retired (source_resolved = 0) 410 noindex,follow self
Not in registry, including real GitHub Skills outside it 404 noindex,follow none from the page; the SEO module adds self
Loading (client only) unchanged noindex,follow none from the page
Skill API error that is not a 404 (for example a D1 overload) 503 with Retry-After: 300 none emitted none from the page
Repository hub, real on GitHub, not in registry 200 (unchanged) noindex,follow self
Repository or owner nonexistent 404 (unchanged) n/a n/a

Decisions:

  • Nonexistent is 404. Nothing was removed on purpose.
  • Retired is 410. The repo already knows via source_resolved = 0, and the existing middleware already sets 410. The page now agrees.
  • A real GitHub Skill outside the registry is 404. The skill route never proxied GitHub; the repository hub is the proxied surface. Serving Skill pages from GitHub would grow the URL space that VISION principle 2 cuts.
  • Owner and repository pages already throw 404 for bots. Production returns 404 for /gh/some-nonexistent-owner and /gh/some-nonexistent-owner/repo. No change there.

The Playwright harness never started locally. nuxi preview --port 5678 runs wrangler on 8787 for the Cloudflare preset, and the Worker read an empty D1 under .output. start:playwright:webserver now applies local migrations and runs wrangler dev on 5678 against the D1 that pnpm dev uses.

Loose ends:

  • nuxt-seo-utils adds a self canonical to every page that is not a Nuxt error, so the 404 page carries one in the built Worker too. That is harmless next to a 404, and the e2e spec now rejects only a canonical to another URL. Throwing a Nuxt error would drop it, but it would also drop the "Skill not found" suggestions.
  • A failed Skill API call used to render 200 with noindex,follow, so a transient error (about 290 "D1 DB is overloaded" in September) could drop a real page. It now answers 503 with Retry-After: 300 and no robots directive, so Google retries and keeps the URL.
  • An API 410 for a Skill with no row is not a separate input. Only a loaded Skill with sourceGone answers 410, as before.

🤖 AI disclosure: Harlan Agent Kit modified this description. My AI open-source policy.

Any made-up /gh/<owner>/<repo>/<skill> URL answered 200 with a thin
page and a canonical to the homepage. Google filed 2,621 of them as
soft 404s, and the open URL space wastes a small crawl budget. A missing
Skill now answers 404 with noindex and no canonical. A page with no Skill
never canonicalises to the homepage.
@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. labels Sep 30, 2026
@harlan-github-agent

harlan-github-agent Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

🤖 MERGED

Harlan Agent Kit posted this automated review. It is not Harlan's personal review or approval. AI open source policy. Last updated: 2026-09-30 09:25 UTC.

GitHub merged this pull request.

  • Logged (15/100): The only e2e guard for the canonical bug can silently pass if the canonical link attribute order changes. View code
    • Ask an agent to verify and fix this finding

c2dfa9ee-4f18-4422-9126-b3765697f500

Selected findings run after merge and open separate pull requests.

@harlan-github-agent harlan-github-agent Bot added harlan-agent-ready The automated Review passed every gate on this head commit. and removed harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-review-required Pull request triage requires an adversarial Review for this head commit. labels Sep 30, 2026
@harlan-zw
harlan-zw added this pull request to stack #319 September 30, 2026 04:43
`nuxi preview --port 5678` starts wrangler on 8787 for the Cloudflare
preset, so Playwright timed out waiting for 5678. The Worker also read
an empty D1 under .output, so every Skill API call failed with 500 and
a missing Skill page rendered its error state with status 200.

The script now applies local migrations and runs wrangler dev against
the same local D1 that `pnpm dev` uses. A fresh checkout gets a
migrated, empty D1.
The page sets no canonical for a missing Skill, but nuxt-seo-utils
adds a self canonical to every page that is not a Nuxt error. That is
harmless on a 404. The spec now fails only when a canonical names
another URL, which is the homepage bug the PR fixes.
@harlan-zw

Copy link
Copy Markdown
Collaborator Author

🤖 Harlan Agent Kit Agent: checked by hand on head 43da1e4, since CI does not run e2e.

Built with pnpm build:test, served by pnpm start:playwright:webserver (the built Worker on wrangler, local D1), requested with a Googlebot user agent:

/gh/some-nonexistent-owner/repo/skill                     -> 404  noindex,follow  canonical self  "Skill not found"
/gh/nutlope/hallmark (indexable, single Skill repo)       -> 200  index,follow    canonical self
/gh/supabase/agent-skills/supabase-postgres-best-practices -> 200  noindex,follow  canonical self
/gh/sleekdotdesign/agent-skills/sleek-design-mobile-apps  -> 410  noindex,follow  canonical self  tombstone body
  • playwright test test/e2e/missing-skill-status.spec.ts passes, with Playwright starting the server itself.
  • A fresh local D1 with only migrations applied also answers 404 for the made-up URL, so a clean checkout works.
  • Production today answers 200 with <link rel="canonical" href="https://skilld.dev"> for the same made-up URL, which the spec rejects.
  • The earlier 200 on the built Worker came from the harness: the Worker read an empty D1 under .output, so the Skill API returned 500 and the page rendered its failed state.

A transient API error rendered a real Skill page as 200 noindex, which could drop it from Google. The failed state now answers 503 with Retry-After and emits no robots directive, so Google retries.
@harlan-zw

Copy link
Copy Markdown
Collaborator Author

🤖 Harlan Agent Kit Agent: checked by hand on head 544034d, since CI cannot cover it.

  • Built Worker (pnpm build:test) on 5678 with migrated local D1: missing Skill 404, retired Skill 410, supabase Skill 200 noindex, as before.
  • Second wrangler dev on 5679 with an empty D1 (Skill API returns 500): every Skill URL answers 503 with Retry-After: 300 and no meta robots.
  • missing-skill-status.spec.ts, full unit suite (2340), typecheck pass; lint has 0 errors.
  • Not covered by e2e: the harness has no failing-D1 mode.

@harlan-github-agent harlan-github-agent Bot added harlan-agent-running An Agent holds a Task on this issue or pull request right now. harlan-agent-ready The automated Review passed every gate on this head commit. and removed harlan-agent-ready The automated Review passed every gate on this head commit. harlan-agent-running An Agent holds a Task on this issue or pull request right now. labels Sep 30, 2026
@harlan-zw
harlan-zw removed this pull request from stack #319 September 30, 2026 09:09
@harlan-zw
harlan-zw merged commit 42c4b92 into main Sep 30, 2026
6 checks passed
@harlan-github-agent harlan-github-agent Bot removed the harlan-agent-ready The automated Review passed every gate on this head commit. label Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant