--- title: "Recording demos for a package README" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Recording demos for a package README} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` ```{r setup, eval = TRUE} library(vhsR) ``` The single most common reason to reach for vhsR is to ship an animated demo at the top of a package's README. This vignette walks through the canonical workflow — from a fresh `record_demo()` call to a GIF that GitHub renders inline. ## The 30-second version ```r record_demo({ x <- 1:5 mean(x) head(cars, 3) }, output = "man/figures/demo.gif") ``` Then in your `README.md` (or `README.Rmd`): ```md ![](man/figures/demo.gif) ``` That's it. The recording runs once on your machine, gets committed to the repository, and renders inline on GitHub, pkgdown, and CRAN's HTML package page (where supported). Treat the GIF as you would any other artefact under `man/figures/` — refresh it when the demo's content changes, otherwise leave it alone. ## Using `README.Rmd` and the `vhsr` knitr engine If you maintain a `README.Rmd`, vhsR registers a `vhsr` knitr engine on package load that records and image-includes in one step. Inside `README.Rmd`: ```` ```{vhsr, output="man/figures/demo.gif"} x <- 1:5 mean(x) head(cars, 3) ``` ```` When you run `devtools::build_readme()` (or knit by hand), the chunk: 1. records a GIF at `output=`; 2. emits a markdown image-include in the rendered `README.md`. Forwarded chunk options are `output`, `backend`, and any pacing or styling argument accepted by `tape_options()` (e.g. `width`, `height`, `font_size`, `theme`, `typing_speed`, `line_pause`, `start_pause`, `paragraph_pause`). See `?tape_options` for the full list. Anything else is ignored. ## Pipe chains type the way you wrote them Multi-line `|>` pipelines record verbatim — the recording shows the pipe form you typed, not the desugared nested-call form R's parser produces internally: ```r record_demo({ library(dplyr) mtcars |> filter(cyl == 6) |> arrange(desc(mpg)) }, output = "man/figures/demo.gif") ``` Same goes for blank lines: an empty line between two statements stays empty in the recording, which composes nicely with `paragraph_pause` when you want a beat between sections. ## Where the GIF lives, and what to commit `man/figures/` is the convention. roxygen, pkgdown, and CRAN's package page all know to look there. Commit the recorded GIF: - Recording is slow (5–30 seconds per run) and CI typically doesn't have vhs installed — there's no point regenerating on every push. - A committed GIF is bit-stable across clones, so a reader's view of your README never depends on a CI artefact. - When the demo content changes, refresh by re-running `record_demo()` (or rebuilding the README) and committing the new GIF. A common make target keeps the workflow explicit: ```make demo: man/figures/demo.gif man/figures/demo.gif: scripts/demo.R R -e 'vhsR::record_demo_file("scripts/demo.R", output = "$@")' ``` ## File-size budget GitHub renders inline GIFs up to about 10 MB but anything over 1–2 MB starts to feel slow on a slow connection. To stay small: - **Keep the demo short.** 4–8 lines of code is plenty. - **Trim the dimensions.** `width = 1000, height = 500` is a good balance. - **Speed up typing.** `typing_speed = "40ms"` (instead of the `"60ms"` default) shaves a meaningful amount of frames. If the GIF is still too big, switch to `.mp4` or `.webm`: ```r record_demo({...}, output = "man/figures/demo.mp4") ``` GitHub's README renderer doesn't autoplay video, but pkgdown and any HTML render do. Embed it with `vhsr_widget()`: ```r vhsr_widget("man/figures/demo.mp4") ``` …which produces a `