This repository was archived by the owner on Oct 13, 2026. It is now read-only.
Repository navigation
feat(seo): canonical URLs, Open Graph tags, JSON-LD and sitemap.xml - #29
Merged
Merged
Conversation
Every built page now carries a canonical URL at the trailing-slash address GitHub Pages serves it from, Open Graph and twitter:card tags, and one JSON-LD block: WebSite plus SoftwareSourceCode on the home page, TechArticle plus BreadcrumbList on doc pages. The build also writes dist/sitemap.xml listing every page. It has no <lastmod> because the deploy checkout is shallow and cannot date pages from git history. Titles and the meta description are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zz-plant
added a commit
that referenced
this pull request
Oct 8, 2026
Brings in the squash merge of #29 so the follow-up PR only shows new changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The 53 published pages had no canonical URL, Open Graph or Twitter tags, or structured data, and the site had no sitemap.
build.mjsnow emits all four. Titles and the meta description are unchanged.Changes
https://refract-org.github.io/refract-docs/. It uses the trailing-slash form because GitHub Pages servesdist/<slug>/index.htmlat<slug>/and 301-redirects<slug>to it. The home page canonical is/refract-docs/, which also consolidates/refract-docs/index.html(that URL returns 200 too).og:title,og:description,og:url,og:type(websiteon home,articleon doc pages),og:site_name("Refract") andtwitter:card=summary.og:titleis the page H1 without the " — Refract" suffix, sinceog:site_namecarries the name.og:descriptionrepeats the existing meta description.@graphper page:WebSite, linked throughaboutto aSoftwareSourceCodenode whosecodeRepositoryis https://github.com/refract-org/refract;TechArticle(headline, description, url,isPartOfthe WebSite) and a two-itemBreadcrumbList(Home, then the page's nav label). The nav groups ("Reference", "Tutorials"…) have no pages of their own, and a breadcrumb item needs a URL, so the trail has no middle level.dist/sitemap.xmllists all 53 pages, sorted.SITE_URL(defaulthttps://refract-org.github.io/refract-docs/) drives the absolute URLs, kept separate fromBASE. A local build with a differentBASEstill points canonicals at production.tests/seo.test.tsbuilds the site and checks every page for one canonical matching its served address, the OG/Twitter values, attribute escaping (comparehas an apostrophe in its title), JSON-LD that parses with the expected nodes, and a sitemap that lists each page exactly once with no<lastmod>.Verification
npm run lint: no errors. The 3 warnings are the existingnoDescendingSpecificityones inassets/style.css.npm test: 4 files, 70 tests pass (63 before this PR).npm run build: 53 pages built.xmllint --noout dist/sitemap.xmlpasses, and the sitemap has 53<loc>entries.TechArticle, 52BreadcrumbList, 1WebSiteand 1SoftwareSourceCodenode.SITE_URL, or dropping the trailing slash from page URLs, fails the new tests.Decisions left to the owner
refract-org/refractGitHub description: "Open infrastructure for agent-readable knowledge change — turns source histories into replayable semantic change events";getExcerpt()already builds a per-page excerpt for the search index and could supply page descriptions.og:image. There is no raster logo. Facebook, X and LinkedIn don't accept the SVG concept diagrams asog:image. The generated PNGs indocs/assets/were rejected too:refract-docs-og.png,-unfurl.pngand-square.pngare mostly empty dark rectangles with small "refract-docs" text, and-github-preview.pngis filled with placeholder "documented route" labels. A purpose-made 1200×630 card would allowog:imagewithsummary_large_image.<title>, and now inog:title.Not done
<lastmod>.deploy.ymlusesactions/checkout@v6with the defaultfetch-depth: 1, sogit logwould give every page the date of the latest commit. To add it later, setfetch-depth: 0in the deploy job and readgit log -1 --format=%cI -- docs/<file>per page.robots.txt. Crawlers only read it at the host root (https://refract-org.github.io/robots.txt), so a copy under/refract-docs/would be ignored.After merge
Submit
https://refract-org.github.io/refract-docs/sitemap.xmlin Google Search Console, under a URL-prefix property forhttps://refract-org.github.io/refract-docs/.🤖 Generated with Claude Code