# Share an R Markdown Report — knitr HTML on a Link, With Comments

Canonical: https://commareports.com/share-rmarkdown-report
Published: 2026-08-22

> rmarkdown::render writes a self-contained HTML file, and it still ends up as an email attachment. Publish it to Comma with one httr call: a stable URL, comments anchored to a specific figure or table, and a revision per rerun.

# Share an R Markdown report

R Markdown solved reproducibility and stopped there. `rmarkdown::render()`
gives you a self-contained HTML file with every plot inlined and every
widget working — and then the distribution story is "email it," because
that's what's available. So the analysis becomes a 12 MB attachment, the
feedback comes back as "the chart on page 4 looks off," and the next
month's rerun starts a second attachment with no relationship to the first.

## Publish from R

```r
rmarkdown::render("report.Rmd", output_file = "report.html")

httr::PATCH(
  paste0("https://commareports.com/api/v1/reports/", Sys.getenv("COMMA_REPORT_ID")),
  httr::add_headers(Authorization = paste("Bearer", Sys.getenv("COMMA_API_TOKEN"))),
  body = list(
    title = paste("Monthly analysis —", format(Sys.Date(), "%Y-%m")),
    html  = readr::read_file("report.html")
  ),
  encode = "json"
)
```

`PATCH` on a saved report id rather than `POST` keeps **one URL** with a
revision per render — the link you sent in March still opens August's
numbers, and any two months can be
[diffed](/share-html-report). Use a [scoped token](/docs/api-tokens) with
`reports:write` and keep it in `.Renviron`, not in the `.Rmd`.

## What changes

- **Comments land on the figure.** "The chart on page 4" becomes a thread
  pinned to that chart, still there at the next rerun. See
  [commenting on HTML](/comment-on-html).
- **Widgets still work.** Self-contained knitr output keeps plotly, DT and
  leaflet interactive inside the sandbox — see
  [interactive HTML reports](/interactive-html-reports).
- **Stakeholders don't need R.** Or a VPN, or an attachment. The
  [sharing model](/docs/sharing) is per report: private, team-visible,
  domain-gated, or named reviewers.
- **The rerun is a schedule, not a reminder.** A
  [routine](/docs/routines) can refresh the report on a cron.

## Limits

- **HTML body: 5 MB.** Self-contained reports with many high-resolution
  figures pass it; render plots at a sane `dpi`, or upload the heavy
  assets separately (25 MB per file) via [assets](/docs/api).
- **Scripts run, sandboxed**: `allow-scripts`, no `allow-same-origin`.

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited
revision history.

**[Create your first report →](https://commareports.com/)**

### Related

- [Jupyter notebooks](/with/jupyter) · [Quarto](/with/quarto) · [Marimo](/with/marimo)
- [EDA reports](/share-eda-report) — profiling output, same pattern
- [Google Docs for HTML](/google-docs-for-html) — why the comment layer matters
