Skip to content

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.

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.

Three pieces cooperate at build time:

  1. rehype-citation parses [@key] syntax during Astro’s markdown pipeline, resolves each key against src/references.json, and emits inline markers plus a bibliography section.
  2. rehype-link-bibliography runs immediately after and linkifies bare URLs and DOIs in the generated bibliography HTML.
  3. citations.css styles both the inline markers and the reference list.

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.

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]] }
}

Pandoc citation syntax works in any MDX file:

SyntaxRendered 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.

Two bugs required workarounds. Both are handled in astro.config.mjs and src/plugins/.

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, broken

The 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);
};
}

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";

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.

src/styles/citations.css handles two areas:

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:

  1. Set font-size: 0 on the span to hide all content (including the bracket text nodes).
  2. Restore font-size on the <a> inside.
  3. Add brackets back with ::before and ::after pseudo-elements on the <a>.

The result is a superscript [1] where the entire token is one clickable link.

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.

FilePurpose
src/references.jsonCSL-JSON bibliography entries
src/ieee.cslIEEE citation style definition
src/styles/citations.cssStyles for inline markers and bibliography
src/plugins/rehype-link-bibliography.tsRehype plugin to linkify URLs in bibliography
astro.config.mjsPlugin registration and safeRehypeCitation wrapper