feat(learn): citation infrastructure + bibliography page#32
Merged
Conversation
Wire up a {cite:id} marker system and YAML references block so learn
articles can carry first-class citations with proper SEO and a11y
treatment. References render as a DPUB ARIA doc-bibliography landmark
with role=doc-backlink, and surface in JSON-LD as ScholarlyArticle /
Book / WebPage citation[] entries with DOI as PropertyValue.
Schema (src/content/config.ts)
- Discriminated reference union (book / journal / web / standard)
- id slug regex, year required for book/journal/standard
- top-level references[] optional on learnCollection (backwards-compat)
- publishedAt frontmatter field added
- per-article author override
Renderer
- buildCitationIndex (src/lib/citations/index.ts) scans sections for
{cite:id} markers and section/item citations[], assigns sequential
numbers in first-appearance order, silently skips dangling ids
- resolveCiteMarkers runs after marked.parse, before mineral-linker
- SectionRenderer threads citationIndex into PropertyList and DataTable
- References.astro component renders the bibliography list with
back-links and external rel=noopener noreferrer
- [...slug].astro wraps index build in try/catch — malformed YAML
cannot 404 a page; passes ordered refs to LearnSchema for JSON-LD
SEO
- LearnSchema author switched from Organization to Person with
@id=https://gemmology.dev/about#author, name="Fabian Moor",
alternateName="Bissbert" (E-E-A-T fix per audit P2-GEO-02)
- Per-article articleAuthor prop allows YAML override
- citation[] array emitted on LearningResource only when references
are provided (never empty array)
- DOIs serialised as { @type: PropertyValue, propertyID: "doi" }
- ISBNs serialised on Book
About page
- Moved /about.astro → /about/index.astro to free /about/sources/
- Updated to show Fabian Moor (Bissbert) authorship with link to
/about/sources/ aggregate bibliography
StructuredData component
- Added alternateName to optional Person prop
…ions CI
- Extract formatAuthors/doiLink/isbnLink/urlLink/formatReference into
src/lib/citations/format.ts; update References.astro to import from there.
- Add src/pages/about/sources/index.astro: aggregate bibliography grouped by
kind (Journal articles / Books / Web sources / Standards), sorted by author
family name then year, with per-entry cited-in links; placeholder shown when
no citations are declared yet.
- Add scripts/validate-citations.mjs: validates {cite:id} markers, citations
arrays, unique ids, valid kinds and years >= 1800; dangling markers exit 1,
unused references warn only.
- Add validate:citations script to package.json.
- Add .github/workflows/ci.yml: lint/typecheck/build pipeline with sync step
before validate:citations, matching deploy.yml style.
|
🚀 Preview deployed to: https://1ed9a86d.gemmology-dev.pages.dev |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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
references:block +{cite:id}inline marker system for/learn/articles, rendering numbered superscript citations and a DPUB-ARIAdoc-bibliographyreferences list at the bottom of each article.citation[]on theLearningResourceJSON-LD asScholarlyArticle/Book/WebPagewith DOIs serialised asPropertyValue { propertyID: "doi" }and ISBNs onBook— surface for AI search and Google citation eligibility.OrganizationtoPerson(E-E-A-T fix per audit P2-GEO-02):name: Fabian Moor,alternateName: Bissbert,@id: https://gemmology.dev/about#author. Per-articleauthoroverride supported in YAML frontmatter./about/sources/aggregate bibliography page, grouped bykind(Journal articles / Books / Web sources / Standards), sorted by author family + year, with which-articles-cite-this back-links. Renders a placeholder until content PRs land.validate:citationsscript + CI step that fails the build on dangling{cite:id}markers and warns on unused references.Architecture
[...slug].astrofrontmatter viabuildCitationIndex, then threaded throughSectionRenderer → PropertyList / DataTable / Referencesas a prop. First-appearance order assigns the[n]number used across the page.resolveCiteMarkersruns aftermarked.parse(so Markdown does not escape the<sup>output) and beforeaddMineralLinks. Dangling ids render as empty string — never break the page.book/journal/web/standard) insrc/content/config.ts.referencesis optional on every learn entry, so this PR is fully backwards-compatible and can ship before any article gets its citations.PropertyValueper schema.org best practice. ISBN →Book.isbn. Both also surface as DOI/WorldCat hyperlinks in the visible references list.Files
src/lib/citations/index.ts— index builder, marker resolver, label helperssrc/lib/citations/format.ts— shared reference formatter (used byReferences.astroand/about/sources/)src/components/learn/References.astro— bibliography section componentsrc/components/seo/LearnSchema.astro— Person author + citation arraysrc/components/seo/StructuredData.astro— optionalalternateNameonPersonsrc/components/learn/SectionRenderer.astro+PropertyList.astro+DataTable.astro— threadcitationIndexthrough render treesrc/content/config.ts— Zod discriminated union for references; optionalpublishedAtandauthorfieldssrc/pages/about/index.astro(moved fromsrc/pages/about.astro) — Fabian Moor (Bissbert) byline, link to/about/sources/src/pages/about/sources/index.astro— aggregate bibliography pagesrc/pages/learn/[...slug].astro— wiresbuildCitationIndexand renders<References>after sectionsscripts/validate-citations.mjs— dangling marker / unused reference detector.github/workflows/ci.yml— addsvalidate:citationsstep before buildPhase 2: citation audits (separate followup PRs)
Nine background audit agents have produced gap matrices for every
/learn/article. Output lives under.tmp/citation-audit-*.md(not committed — used as input to bulk YAML edits ingemmology-knowledge):Top corpus-wide sources: Read 2014 Gemmology (DOI 10.4324/9780080507224) · Hughes 2017 Ruby & Sapphire (ISBN 978-0-9645097-6-4) · Palke et al. 2019 G&G geographic-origin trilogy · Nassau 2001 Physics and Chemistry of Color · Schumann 2009 Gemstones of the World · Gübelin & Koivula Photoatlas.
Each audit file ships ready-to-paste YAML
references:blocks and inline{cite:id}placement notes — Phase 3 is the bulk edit pass ingemmology-knowledge.Test plan
npm run build— 913 pages, no errorsnpm run validate:citations— exits 0 on current content (no citations yet)/about/sources/renders placeholder when no citations exist/about/renders updated Fabian Moor (Bissbert) byline + link to sources/learn/identification/treatments/(the highest-citation-density article)