---
title: "Getting Started with livelink"
vignette: >
  %\VignetteIndexEntry{Getting Started with livelink}
  %\VignetteEngine{quarto::html}
  %\VignetteEncoding{UTF-8}
format:
  html:
    embed-resources: true
knitr:
  opts_chunk:
    collapse: true
    comment: '#>'
---

```{=html}
<style>
.ll-fig{display:block;margin:1.5rem auto;max-width:100%;height:auto}
.ll-dark{display:none}
@media (prefers-color-scheme:dark){.ll-light{display:none}.ll-dark{display:block}}
[data-bs-theme=light] .ll-light{display:block}
[data-bs-theme=light] .ll-dark{display:none}
[data-bs-theme=dark] .ll-light{display:none}
[data-bs-theme=dark] .ll-dark{display:block}
</style>
```

```{r setup}
#| include: false
library(livelink)
```

## The idea

Sharing R code usually means asking someone to install something. livelink asks
nothing: it packs your code *into a URL*, and the recipient clicks it and is looking
at a running R session in their browser.

There is no server and no upload. The code is compressed and encoded into the part of
the URL after the `#`, which browsers never send anywhere. The link is the payload.

![Your code is serialized to JSON, gzipped, base64-encoded, and placed in the fragment of a webR URL after the `#`. Opening the link runs it in the browser.](../man/figures/pipeline-light.svg){.ll-fig .ll-light}
![](../man/figures/pipeline-dark.svg){.ll-fig .ll-dark aria-hidden="true"}

Two destinations are supported:

- **[webR](https://docs.r-wasm.org/webr/latest/)**: a full R console and editor in the browser.
- **[Shinylive](https://shiny.posit.co/py/get-started/shinylive.html)**: Shiny apps, R or Python, with no server.

## Your first link

Pass some code. Get a link.

```{r}
webr_repl_link("plot(1:10)")
```

In a rendered document like this one the object becomes a clickable link, so you can
open it right from the page. At an interactive console it prints its details instead,
and `as.character()` gives you the bare URL string either way.

You can skip the quotes entirely and hand it a braced expression, which is easier to
write and lets your editor highlight the code:

```{r}
webr_repl_link({
  data(mtcars)
  plot(mtcars$mpg, mtcars$wt)
})
```

::: {.callout-note}
## Comments and expression input

Expression input reconstructs your code from R's *source references*. Those exist in
an interactive session, but not when a document is knitted, so comments inside
`{ }` are dropped from the link when this vignette is rendered.

If your code has comments worth keeping, pass it as a string or a file path, or write
it as a chunk. See [Links inside documents](links-in-documents.html).
:::

You can also point at a file:

```{r}
script <- tempfile(fileext = ".R")
writeLines(c("# fit a model", "lm(mpg ~ wt, data = mtcars)"), script)

webr_repl_link(script)
```

...or, in an interactive session, copy code to your clipboard and call
`webr_repl_link()` with no arguments at all.

## Making it run on arrival

By default the recipient sees your code, ready to run. Set `autorun = TRUE` and it
runs the moment the page opens, which is right for a demo and wrong for an exercise.

```{r}
webr_repl_link("hist(rnorm(1000))", autorun = TRUE)
```

## Choosing what they see

webR opens with four panels: an **editor** for your code, a **terminal** for the R
console, a **files** browser, and a **plot** pane. `panels` names the ones you want,
and the rest never appear.

![webR has four panels. `panels` names the ones you want, and the rest never appear. Omit it and all four are shown.](../man/figures/panels-light.svg){.ll-fig .ll-light}
![](../man/figures/panels-dark.svg){.ll-fig .ll-dark aria-hidden="true"}

```{r}
webr_repl_link("plot(1:10)", panels = c("editor", "plot"))
```

The names are joined into the URL's query string, `?mode='editor-plot'`, so you can
read a link and tell what the recipient will land on. Omit `panels` and webR shows
everything:

```{r}
webr_repl_link("plot(1:10)")
```

Trimming the panels is worth doing when the terminal would only invite someone to
wander off. [Teaching with livelink](teaching.html) leans on it.

## A Shiny app instead

`shinylive_r_link()` does the same for a Shiny application.

```{r}
app <- "
library(shiny)
ui <- fluidPage(
  sliderInput('bins', 'Bins:', 1, 50, 30),
  plotOutput('hist')
)
server <- function(input, output) {
  output$hist <- renderPlot(hist(faithful$waiting, breaks = input$bins))
}
shinyApp(ui, server)
"

shinylive_r_link(app, mode = "app")
```

`mode = "app"` shows the running application. `mode = "editor"` shows the code beside
it, which is what you want when the point is to teach. Python apps work the same way
through `shinylive_py_link()`.

::: {.callout-tip}
## Why a string, and not a braced expression?

`shinylive_r_link({ ... })` does work. But a Shiny app is source text destined for
*another* runtime, and putting `library(shiny)` inside braces makes it look like R
code your own package runs: `R CMD check` scans vignettes for `library()` calls and
will report shiny as an undeclared dependency of livelink, which it is not.

Braces are for R you want executed in webR. For a Shiny app, a string or a file path
says what you mean.
:::

## What a link actually looks like

Nothing here is magic, and the URL is readable if you know where to look.

![A webR URL in five parts: the base address, the version, the panels to show, the `#code=` fragment carrying your files, and the flags saying how the payload was encoded.](../man/figures/url-anatomy-light.svg){.ll-fig .ll-light}
![](../man/figures/url-anatomy-dark.svg){.ll-fig .ll-dark aria-hidden="true"}

The flags at the end say how the payload was encoded: `j` for JSON, `z` for gzip,
`m` for msgpack, `u` for uncompressed, `a` for autorun. livelink writes `jz`, and webR's
own share button writes `mz`. livelink reads both.

## Going the other way

Because the files live in the URL, any link can be turned back into files, with no
network access and no cooperation from a server.

```{r}
url <- as.character(webr_repl_link("plot(1:10)"))

preview_webr_link(url)
```

`preview_webr_link()` inspects a link *without writing anything*, which is the
sensible way to open a link someone sent you. `decode_webr_link()` extracts the files
once you have decided you trust them.

## Links inside a document

If you write in Quarto or R Markdown, a chunk can carry its own link. Add
`livelink: true` to an ordinary chunk and it keeps running exactly as before, output
and plots and all, with a link added underneath:

````
```{{r}}
#| livelink: true
#| autorun: true
data(mtcars)
plot(mtcars$mpg, mtcars$wt)   # a comment that survives
```
````

Your comments reach the link, which they do not when a `{ }` expression is knitted.
[Links inside documents](links-in-documents.html) covers this properly: the hook, the
engine, every chunk option, and how to set them once for a whole document.

## Where to next

- **[Multi-file projects and Shiny apps](webr-and-shinylive.html)**: projects, apps in R and Python, and whole directories.
- **[Decoding and previewing links](decoding-links.html)**: turning a link back into files, and inspecting one before you trust it.
- **[Links inside documents](links-in-documents.html)**: the chunk hook and the chunk engine, and every option they take.
- **[Teaching with livelink](teaching.html)**: exercise and solution pairs, whole course directories, and embedding links in notes.
