Tutorial: your first manuscript in 15 minutes
This tutorial walks one path. By the end you will have a Quarto
manuscript with citations resolved automatically from DOIs and
PubMed IDs, rendering itself on every push, deployed to GitHub Pages
with a /v/<commit-sha>/ immutable permalink for each commit.
Budget: 15 minutes if you have Quarto, uv, and gh already on
your machine. First render takes longer because Quarto installs
TinyTeX the first time it sees a PDF format. After that, every
render is fast.
You will not learn why the design choices are this way — that’s the Design and Citation pipeline pages’ job. This tutorial is doing, not understanding.
Before you start
Section titled “Before you start”You need:
- Quarto ≥ 1.4 —
quarto --version. Install Quarto if needed. uv—uv --version. Install uv if needed; it handles the Python install for you transparently.gh(the GitHub CLI) —gh --version. Install gh if needed.- A GitHub account authenticated with
gh auth login.
That’s it. No separate Python install, no manubot install, no Quarto extensions to add.
1. Install quartobot
Section titled “1. Install quartobot”uv tool install quartobotThis puts quartobot on your user PATH so Quarto’s pre-render
subprocess can find it without venv activation. Confirm:
quartobot --versionYou should see quartobot, version 0.2.0 (or later).
2. Create the project
Section titled “2. Create the project”Use Quarto’s own scaffolder for the project shape:
quarto create project manuscript my-papercd my-paperQuarto writes a manuscript-shaped directory: an index.qmd, a
_quarto.yml, and the layout pandoc expects for a single-document
manuscript.
3. Wire in citation resolution
Section titled “3. Wire in citation resolution”Layer the citation pipeline on top:
quartobot initinit adds two new files and modifies .gitignore: a seed
references.bib you can hand-curate any non-registrar references
into, plus .gitignore lines for _book/, _freeze/, .quarto/,
*_files/, **/*.quarto_ipynb, and references.json. Because
quarto create project already wrote a _quarto.yml, init
won’t touch it; instead it prints a YAML snippet to paste in
yourself. Copy the snippet and merge it into your _quarto.yml
under the existing project: block — it adds the
pre-render: line plus a bibliography: list with both
references.bib and references.json.
That’s the minimum. If all you want is citations resolved from
@doi: and friends, stop here.
4. Write a paragraph
Section titled “4. Write a paragraph”Open index.qmd and replace the body with:
The manubot pattern [@doi:10.1371/journal.pcbi.1007128] runs scholarlymanuscripts as git repositories that build themselves on every commit,resolve citations from persistent identifiers, and hand outimmutable permalinks per commit. The GTEx Consortium's pilot analysis[@pmid:23685459] shipped a 168-author preprint using a similarcollaborative-PR pattern; both are early examples of treating apaper as software rather than a Word document.Two cite keys, two registrars. Nothing else to configure.
5. Render locally
Section titled “5. Render locally”quarto renderFirst render installs TinyTeX (Quarto handles this; takes 1–2 minutes). On the second render and after, it’s seconds.
The pre-render hook fires before pandoc runs. It:
- Scans
index.qmdfor cite keys. - Calls each registrar (Crossref for the DOI, PubMed for the PMID) to resolve canonical metadata.
- Writes the resulting CSL JSON to
references.json. - Hands control back to pandoc, which reads
references.jsonand formats the citations.
Open _output/index.html (or index.pdf). The citations show as
formatted references with author names, journal, year. No empty
[?] placeholders.
Re-run quarto render. Now it’s near-instant — the pre-render hook
sees references.json already exists with both keys cached, skips
the network round-trip, and pandoc renders straight through.
6. Add the publish-on-every-commit CI
Section titled “6. Add the publish-on-every-commit CI”If you want every push to your GitHub repo to render the manuscript,
deploy it to GitHub Pages, embed a “this version: <sha>” banner in
the rendered HTML, and post a sticky preview comment on each PR —
add the second layer:
quartobot use github-ciThis scaffolds .github/workflows/render.yml (the trigger), the
PR-preview cleanup workflow, the version-banner Quarto include, and
prints a YAML snippet to merge into your _quarto.yml so the banner
appears in the rendered HTML.
Skip this step entirely if you already have CI you’re happy with,
or if you plan to publish via quarto publish. The citation
pipeline from step 3 works the same either way.
Add the snippet that quartobot use github-ci printed to your
_quarto.yml. It will look roughly like:
format: html: include-in-header: - _version-banner.html7. Push to GitHub
Section titled “7. Push to GitHub”gh repo create my-paper --source=. --public --pushgh creates the repo, pushes your commit, and gives you the URL.
The render workflow fires on push. Watch it land:
gh run watchWhen the workflow finishes, GitHub Pages serves your manuscript at
https://<your-handle>.github.io/my-paper/. Every commit also
deploys to a versioned subdirectory: https://<your-handle>.github.io/my-paper/v/<sha>/index.html.
The version banner in the rendered HTML links you between them.
8. Open a pull request
Section titled “8. Open a pull request”Make a change. Push to a branch. Open a PR.
git checkout -b add-context# edit index.qmd, add another sentence with another citationgit add index.qmdgit commit -m "Add context paragraph"git push -u origin add-contextgh pr create --fillWithin a couple of minutes a sticky comment lands on the PR with a link to a preview render. Reviewers see exactly what your branch renders to without checking it out locally.
When you merge the PR, quartobot use github-ci’s cleanup workflow
removes the preview directory from gh-pages; the merge commit gets
its own /v/<sha>/ permalink alongside the latest.
You now have
Section titled “You now have”- A manuscript that builds itself on every push.
- Citations resolved from registrars at render time, cached so CI never sees a network blip mid-render.
- An immutable
/v/<sha>/URL for every commit anyone can cite. - PR previews via sticky comment.
- A version banner in the rendered HTML pointing at “this version” and “the latest version” of the paper.
Where to next
Section titled “Where to next”- CLI reference — every command, every flag.
- MCP server — point Claude Desktop, Codex, or Gemini
Code Assist at
quartobot mcpso an agent can call theresolve_citationtool while you draft. - Migrating from manubot — if you have a manubot manuscript and want to translate the layout.
- Design — the architecture decisions and prior art.