chore(pages): replace the gh-pages docs mirror with a branded link stub - #62
Conversation
The MkDocs build published to gh-pages was a second live copy of docs/, duplicating coder-eval.com/docs. Both copies self-canonicalized, which splits search signals and lets the wrong host rank for our own docs — and the mirror had drifted, still serving BYOD/ and CODEX_AGENT_GUIDE/ after those pages were renamed upstream, with a sitemap.xml advertising all 14 stale URLs for indexing. Replace it with a single static page linking to coder-eval.com/docs, the project site, and the repo. Pages serves 404.html for unknown paths, so the same stub catches every old deep URL without a file per route. It carries `noindex, follow` rather than a canonical pointing at /docs: the stub's content differs from the target, and Google discourages combining noindex with rel=canonical and ignores canonicals across substantially different pages. Net effect: the duplicate cluster drops to zero indexed pages. The mkdocs gh-deploy step is removed, not commented out — left one uncomment away, a future run would silently restore the duplicate. mkdocs itself stays: mkdocs.yml remains the docs IA source of truth (CE028 generates the index surfaces from its nav:, the website derives its sidebar from it) and `mkdocs build` still verifies anchors locally. Only the publishing of a second site is gone. gh-pages is force-replaced with a fresh single-commit history so none of the old output — sitemap included — survives. Verified: workflow YAML parses, the assemble step dry-run produces index.html/404.html/.nojekyll/llms.txt, all three links return 200, the page renders in light and dark, and `make lint` passes (166). Co-Authored-By: Claude <noreply@anthropic.com>
Dresses up the redirect stub so it reads as ours rather than as a bare fallback: the Coder Eval wordmark above the heading, and a brand-orange bar linking to the repo with its star and fork counts. The wordmark is inlined from the website's src/assets/logo-light.svg rather than linked. The light and dark variants differ only in four navy fills (the three icon bars and the "Coder" text group — "Eval" and the arc are always brand orange), so those four become `currentColor` and one 3.5 KB copy serves both colour schemes. Substitution was scripted, not hand-typed, and asserts it recoloured exactly four fills and left the orange intact. Keeps the page free of external stylesheets, fonts, and images. Palette switched from approximations to the real brand values taken from those assets: #FA4616 orange, #10233A navy, #F5F7FA off-white. Star/fork counts ship as a committed snapshot so the bar is never blank, then refresh from api.github.com on load. Unauthenticated is 60 req/hour/IP, ample for a page nobody should land on, and any failure silently leaves the snapshot. GitHub's own octicon paths are inlined for the mark, star, and fork glyphs. Verified in-browser: renders in both colour schemes (dark @media rule deleted at runtime to confirm the light path), and the refresh was proven to work by poisoning the counts to 999 and watching the fetch restore 107/2. Co-Authored-By: Claude <noreply@anthropic.com>
Requested as a loading state for the star/fork counts. Built inverted from the obvious reading, because a spinner in the markup would be worst for the no-JS case it was meant to serve: with scripting off nothing would ever resolve it, so it would claim "fetching…" forever and read as broken. So the snapshot stays in the HTML and the spinner is installed BY the script — it therefore only appears where JS is also able to finish the job. No-JS visitors and crawlers get 107/2, which is stale at worst, never a lie. Every exit resolves the spinner: live values on success; the snapshot back on network error, non-2xx, a payload missing either count, or the 4s deadline. The count cell reserves 3 digits of width so the swaps don't shift the bar. The deadline restores the UI itself rather than only calling abort(). Relying on the abort was a real hole — a fetch that ignores the signal would spin forever, exactly the failure being avoided — and a stubbed hanging request reproduced it before this was fixed. A `settled` flag makes the race single-shot so a response landing after the deadline cannot overwrite the restored snapshot. Verified in-browser against a stubbed network, running this exact script: spinner renders mid-flight; hang restores after 4s; reject, HTTP 500, partial payload, and a 6s-late response all settle on 107/2 with no cell left spinning (the late 99999/88888 payload was correctly discarded). Markup contains zero spinner elements, so the no-JS path is the static snapshot. Co-Authored-By: Claude <noreply@anthropic.com>
Simplifies the repo bar's star/fork counts on two instructions: no committed values, and a failed fetch should keep spinning rather than fall back. The spinner is now the initial state in the markup and the only fallback, so the previous scaffolding — a snapshot Map, restore-on-failure, the 4s AbortController deadline, and the `settled` race guard — all had nothing left to do and is gone. Net 70 lines deleted for 20 added; the script is 10 lines. Anything that isn't a live number stays a spinner: offline, non-2xx, a payload missing a field, or scripting disabled. Resolution is per cell, so a partial payload fills what it has and leaves the rest spinning, rather than needing an all-or-nothing rule. Tradeoff, accepted deliberately: with JavaScript off the spinner never resolves. That is the cost of never publishing a count that is wrong within days, on a stub page nobody should be landing on. Verified in-browser: live load fills 107/2; network reject, a request that never settles, and a payload missing forks_count all leave the spinner in place; markup contains no numeric literals for the counts. Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @uipreliga's task in 1m 24s —— View job Code Review In Progress
|
The page named the product and said the docs had moved, but never described what it is. Anyone arriving from a stale link had to click through to find out. Leads with the product now: `Coder Eval` as the h1, then a one-sentence description (open-source framework, evaluates and benchmarks AI coding agents and Claude Code skills, sandboxed real-agent runs against declarative YAML tasks, scores the files and commands produced), with the moved notice demoted to a secondary line. Wording mirrors coder-eval.com and the package metadata so the product is described identically everywhere. Adds a matching <title> and meta description. Note these do NOT help ranking — the page is `noindex` — they are for link previews and shared URLs; the comment above them says so, so nobody later mistakes them for SEO copy that is doing work it isn't. The wordmark is now aria-hidden. It renders the same text as the new h1, so a screen reader was announcing "Coder Eval" twice; the h1 is the accessible name and the logo is decorative. Co-Authored-By: Claude <noreply@anthropic.com>
…wice Three copy fixes. The notice now links coder-eval.com/docs instead of naming it as plain text — it is the sentence a visitor actually reads to find where the docs went, so it should be clickable. "Coder Eval" was rendered twice, by the wordmark and again by the h1 directly beneath it. The h1 is now visually hidden: it stays for document structure and is the accessible name for the page (the logo is aria-hidden), while the eye sees the wordmark once and then the description. The lead paragraph takes the visual weight the heading was carrying. Linking the docs in the notice then made the "Documentation" list row a second copy of the same URL two lines apart, so that row is gone. Each destination now appears exactly once: docs in the notice, the project site in the list, the repo in the bar. Co-Authored-By: Claude <noreply@anthropic.com>
bai-uipath
left a comment
There was a problem hiding this comment.
LGTM. Deleting the mirror is right, and 404.html-as-stub is the correct answer to 15 dead routes. All follow-up below.
-
Pull the wordmark out into a committed
.svg. 5.1 KB of inline SVG is 35% of the page, 3.1 KB of it font outlines for two words the hidden<h1>already renders. Fix: reference it root-absolute (/coder_eval/logo.svg), since404.htmlserves at arbitrary depths, and use a<picture>for light/dark because an external<img>can't inheritcurrentColor;website/src/assets/already has both variants. -
The multi-repo split is the real exposure, not the stub.
docs/is the source of truth here but publishing now lives entirely incoder_eval_uipath/website/viascripts/sync-docs.mjs. After this merges nothing in this repo publishes docs anywhere, andmkdocs-material[imaging]>=9.5,<10is pinned nowhere whileCLAUDE.md:208still says to verify anchors withmkdocs build. -
coder-eval.com is served from an unmerged branch.
coder_eval_uipath62 has been open since Jul 22 at 73 commits and the live site tracks its head. The stub hardcodes/llms-full.txtand copieslogo-light.svg, both of which exist only there. Not blocking (site is live, all links 200). Fix: land internal 62, and note the logo's source commit so it reads as a copy. -
Merging doesn't take effect.
workflow_dispatch-only leaves the stale mirror live until someone remembers the Actions tab. Fix:push:onmainwithpaths: ['.github/pages-stub/**', '.github/workflows/docs.yml']. -
Minor:
#FA4616as text fails WCAG AA (3.53:1 on white, same for white-on-orange in the bar; rest of the palette is 5.5:1+); with JS off or rate-limited both counts spin forever, so consider dropping them;noindexis a no-op for the 15 deep paths, which now 404 on status.

Why
uipath.github.io/coder_eval/was serving a second live copy ofdocs/, duplicating coder-eval.com/docs. Verified before this change:<link rel="canonical" href="https://uipath.github.io/coder_eval/">rather than deferring to coder-eval.com. Google elects one canonical per duplicate cluster, and nothing told it which to pick.uipath.github.io/robots.txtis 404, so nothing blocked crawling, and the mirror shipped its ownsitemap.xmlactively advertising all 14 URLs for indexing./BYOD/and/CODEX_AGENT_GUIDE/, pages renamed upstream toDATASETS.mdandagents/CODEX.md. So the risk wasn't only duplication — the copy competing with us was out of date.There's no penalty for duplicate content, but the mechanical costs are real: split link equity on a domain whose measured problem is a shortage of inbound links, and Search Console reporting "Duplicate, Google chose different canonical" for pages we're verified for — optimizing without feedback.
What
Replaces the MkDocs deploy with a single branded stub page.
.github/pages-stub/index.html— Coder Eval wordmark, a one-sentence description of what the product is, a link to the docs, and a brand-orange bar linking to this repo with its live star/fork counts..github/workflows/docs.yml— publishes that stub instead of runningmkdocs gh-deploy, force-replacinggh-pagesso none of the old output (sitemap included) survives.404.htmlis a copy of the stub, so Pages serves it for every old deep URL without needing a file per route.Decisions worth reviewing
noindex, followrather than a canonical to/docs. The stub's content differs from the target; Google discourages combiningnoindexwithrel=canonicaland ignores canonicals across substantially different pages. This takes the duplicate cluster to zero indexed pages rather than one.The mkdocs deploy is deleted, not commented out. It had already been commented out once, and that is exactly how the duplicate got published — one uncomment away.
mkdocs.ymlitself is untouched and still required: CE028 generates the index surfaces from itsnav:, the website derives its sidebar from it, andmkdocs buildstill verifies anchors locally. Only the publishing of a second site is gone.One logo copy, not two. The wordmark is inlined from the website's
src/assets/logo-light.svg. The light and dark variants differ in only four navy fills (three icon bars and the "Coder" text group — "Eval" and the arc are always brand orange), so those becamecurrentColorand one 3.5 KB copy serves both colour schemes. The substitution was scripted with assertions that it recoloured exactly four fills and left#FA4616intact — no path data was hand-copied. The page also moved onto the real brand palette (#FA4616,#10233A,#F5F7FA) from my earlier approximations.Counts are never hardcoded. A committed star count is wrong within days, so the markup ships spinners and the script fills them from
api.github.com. Anything that isn't a live number stays a spinner — offline, non-2xx, missing field, or scripting disabled. Resolution is per cell, so a partial payload fills what it has. Accepted tradeoff: with JS off the spinner never resolves, which is the price of never publishing a stale number on a page nobody should land on. Unauthenticated API is 60 req/hour/IP.An earlier revision carried a snapshot value plus restore-on-failure, a 4s
AbortControllerdeadline and a race guard; dropping the hardcoded values made all of it dead weight, so the script is now 10 lines.The page says what Coder Eval is. It previously named the product and said the docs had moved, so anyone arriving from a stale link had to click through to learn what it was. It now leads with a one-sentence description, worded to match coder-eval.com and the package metadata so the product is described identically everywhere. There is a matching
<title>andmeta description— but note those are for link previews, not ranking: the page isnoindex, so search engines will not surface it. A comment above them says so, so they aren't later mistaken for SEO copy doing work it isn't.No text is repeated. The wordmark already renders "Coder Eval", so the
<h1>beneath it was the same two words twice; the heading is now visually hidden, keeping document structure and serving as the accessible name (the logo isaria-hidden, which also stops a screen reader announcing the name twice). Linkingcoder-eval.com/docsinside the notice then made the "Documentation" list row a second copy of the same URL two lines apart, so that row is gone. Each destination appears exactly once: docs in the notice, the project site in the list, the repo in the bar.Verification
index.html,404.html,.nojekyll,llms.txt.@mediarule at runtime, so the wordmark'scurrentColorwas actually exercised).forks_counteach leave the spinner in place. Markup contains no numeric literals for the counts.make lintpasses (166).After merge
This needs one manual
workflow_dispatchrun of the Pages stub workflow from the Actions tab — merging alone does not replace the live mirror.Not in scope
sharpHIGH Dependabot alert onmain(transitive inevalboard, fixed in 0.35.0) is pre-existing and unrelated./llms.txton the website was pointing three links at theuipath.github.iomirror; that is fixed separately in the website repo, along with adding/llms-full.txt.