Citations and Bibliographies
This site supports Pandoc-style inline citations that resolve against a shared bibliography. Write [@key] in any MDX file and a numbered reference appears inline, with a full bibliography appended at the bottom of the page.
Quick start
Section titled “Quick start”Add an entry to src/references.json using CSL-JSON format, then cite it by its id:
The GaLore paper [@zhao2024galore] introduced gradient low-rank projection.That renders a superscript [1] linking to the bibliography section at the bottom of the page.
How it works
Section titled “How it works”Three pieces cooperate at build time:
- rehype-citation parses
[@key]syntax during Astro’s markdown pipeline, resolves each key againstsrc/references.json, and emits inline markers plus a bibliography section. - rehype-link-bibliography runs immediately after and linkifies bare URLs and DOIs in the generated bibliography HTML.
- citations.css styles both the inline markers and the reference list.
Pipeline configuration
Section titled “Pipeline configuration”Both plugins are registered as rehype plugins in astro.config.mjs:
markdown: { rehypePlugins: [ [ safeRehypeCitation, { bibliography: ['src/references.json'], csl: 'src/ieee.csl', linkCitations: true, showTooltips: true, }, ], rehypeLinkBibliography, ],},The csl option points to an IEEE citation style file. Other CSL styles from the CSL repository can be dropped in and referenced instead.
Adding references
Section titled “Adding references”CSL-JSON format
Section titled “CSL-JSON format”Each entry in src/references.json is a CSL-JSON object. The id field is the citation key you use in [@...] syntax. Two examples:
Journal article or preprint:
{ "id": "zhao2024galore", "type": "article", "title": "GaLore: Memory-Efficient LLM Training by Gradient Low-Rank Projection", "author": [ { "family": "Zhao", "given": "Jiawei" }, { "family": "Zhang", "given": "Zhenyu" } ], "issued": { "date-parts": [[2024]] }, "DOI": "10.48550/ARXIV.2403.03507", "URL": "https://arxiv.org/abs/2403.03507"}Web page:
{ "id": "rehype-citation-repo", "type": "webpage", "title": "rehype-citation: Rehype plugin for citations and bibliographies", "author": [{ "literal": "github.com" }], "URL": "https://github.com/timlrx/rehype-citation", "accessed": { "date-parts": [[2026, 3, 28]] }}Citation syntax
Section titled “Citation syntax”Pandoc citation syntax works in any MDX file:
| Syntax | Rendered as |
|---|---|
[@zhao2024galore] | Numbered reference, e.g. [1] |
[@zhao2024galore; @rehype-citation-repo] | Multiple references, e.g. [1], [2] |
[-@zhao2024galore] | Suppress author (year only in author-date styles) |
With IEEE style, all three produce numbered markers. The distinction matters more with author-date styles like APA or Chicago.
Workarounds
Section titled “Workarounds”Two bugs required workarounds. Both are handled in astro.config.mjs and src/plugins/.
Options mutation bug
Section titled “Options mutation bug”rehype-citation mutates the options.bibliography array when resolving relative paths to absolute paths. Since Astro reuses the same options object across every MDX file, the second file sees an already-resolved absolute path and path.join doubles it:
/project/docs/src/references.json # first file, correct/project/docs/project/docs/src/references.json # second file, brokenThe safeRehypeCitation wrapper clones both the options object and the bibliography array before each invocation:
function safeRehypeCitation(opts) { return async (tree, file) => { const cloned = { ...opts, bibliography: [...opts.bibliography] }; return rehypeCitation(cloned)(tree, file); };}Node vs. browser export resolution
Section titled “Node vs. browser export resolution”The rehype-citation package exports both a Node and a browser build. Its package.json maps the default export condition to the browser build, which Vite picks up during Astro’s build pipeline. The browser build cannot read local files.
The fix is to import the Node build explicitly:
import rehypeCitation from "rehype-citation/node/rehype-citation.mjs";Bare URLs in bibliography
Section titled “Bare URLs in bibliography”rehype-citation outputs URLs and DOIs as plain text in the bibliography. The rehype-link-bibliography plugin (src/plugins/rehype-link-bibliography.ts) runs after rehype-citation, finds the #refs.references container, and wraps bare URLs and DOI patterns in <a> tags.
It operates on the HAST (HTML Abstract Syntax Tree) that rehype already parsed, not on raw HTML strings. The regex patterns match inside plain text node values only.
Styling
Section titled “Styling”src/styles/citations.css handles two areas:
Inline markers
Section titled “Inline markers”rehype-citation renders inline citations as:
<span id="citation--key--1">[<a href="#bib-key">1</a>]</span>The square brackets are bare text nodes outside the <a> tag, so they are not clickable. The CSS fixes this:
- Set
font-size: 0on the span to hide all content (including the bracket text nodes). - Restore
font-sizeon the<a>inside. - Add brackets back with
::beforeand::afterpseudo-elements on the<a>.
The result is a superscript [1] where the entire token is one clickable link.
Reference list
Section titled “Reference list”The bibliography section uses a two-column CSS grid per entry: a narrow column for the reference number and the rest for the citation text. Reference numbers are accent-colored and right-aligned. Entries are separated by subtle borders.
File inventory
Section titled “File inventory”| File | Purpose |
|---|---|
src/references.json | CSL-JSON bibliography entries |
src/ieee.csl | IEEE citation style definition |
src/styles/citations.css | Styles for inline markers and bibliography |
src/plugins/rehype-link-bibliography.ts | Rehype plugin to linkify URLs in bibliography |
astro.config.mjs | Plugin registration and safeRehypeCitation wrapper |