Share a bookdown book
bookdown is what R users reach for when a report grows past one document:
numbered chapters in separate .Rmd files, cross-references that resolve
(\@ref(fig:coverage-plot)), citations from a .bib, and a rendered site with
a sidebar and full-text search.
bookdown::render_book("index.Rmd", "bookdown::bs4_book") # → _book/
And the output is a directory:
_book/
├─ index.html ← entry point
├─ methods.html results.html appendix.html
├─ search.json ← fetched at load
├─ libs/ ← jQuery, Bootstrap, MathJax
└─ figures/ *_files/ ← plots
Every failure people hit with this comes from treating that directory as a
file. Sending index.html alone gives the reader chapter one with dead links to
every other chapter. Zipping it makes them unpack and hunt for the entry point.
And opened from file://, the search index fetch is blocked by the browser, so
search silently returns nothing.
The published fallback is usually GitHub Pages or Netlify — which means a repo, a build step, a deploy, and a public URL whether or not the content should be public.
Publish the folder
Drag _book/ (or a zip of it) into the app:
index.htmlbecomes the report body.- Every chapter page,
search.json, thelibs/bundle and the figure directories upload alongside it, and their relative references are rewritten to the uploaded copies. - Scripts run inside a sandboxed iframe (
allow-scripts, noallow-same-origin), so the sidebar, the search box and MathJax all work — including the search index fetch thatfile://blocks.
Or PATCH the entry file from the render script:
Rscript -e 'bookdown::render_book("index.Rmd", "bookdown::bs4_book")'
curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
-H "Authorization: Bearer $COMMA_API_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile html _book/index.html \
--arg t "Methods handbook — 2026 edition" '{title: $t, html: $html}')"
When one file is the better answer
If what you have is a long report rather than a book, the folder question goes away:
output:
bookdown::html_document2:
self_contained: true
toc: true
toc_float: true
That inlines the figures and the libraries into one file. You lose per-chapter URLs and the sidebar's cross-document navigation; you gain an artifact that is trivially portable. For anything under about thirty pages it is usually the right trade.
Draft rounds
A book in review gets re-rendered constantly. PATCH one report id and the link in the reviewers' calendar invitation stays correct:
Rscript -e 'bookdown::render_book("index.Rmd")'
# …PATCH as above…
One URL, a revision per render. Reviewers reading revision 4 can see what changed since revision 3, which is the part an emailed PDF cannot do.
What review adds
- Anchored threads on a paragraph or a figure, so a correction sits where the error is — see commenting on HTML.
- Revisions, so the review round has a record.
- Access per report — private, team, domain-gated or named reviewers, which is how a draft stays a draft. See the sharing model.
Limits
- Entry HTML: 5 MB. Assets: 25 MB per file, 250 MB and 500 files total. A long book with many high-resolution plots is the case that approaches the file count — render figures at a sensible DPI rather than publishing 600-dpi PNGs nobody will zoom into.
- 60 requests/minute per token.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.