--- title: "Getting started with brochure" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting started with brochure} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` A `{shiny}` app usually lives at a single url, and everything you show is a matter of hiding and showing pieces of one page. `{brochure}` takes the other road: an app serves several endpoints, and each of them is its own page, with its own UI and its own server function. ```{r} library(shiny) library(brochure) ``` ## A page `page()` binds an href to a UI and a server function. The server is optional: a page that only shows static content does not need one. ```{r} home <- function() { page( href = "/", ui = tagList( h1("Home"), plotOutput("plot") ), server = function(input, output, session) { output$plot <- renderPlot(plot(mtcars)) } ) } contact <- function() { page( href = "/contact", ui = tagList( h1("Contact"), tags$p("here@example.com") ) ) } ``` ## An app `brochureApp()` replaces `shinyApp()`, and takes the pages: ```{r} brochureApp( home(), contact() ) ``` Navigating between pages is done with plain links — `tags$a(href = "/contact")`. There is no router to configure on the client: a link is a real navigation, and the browser asks the server for that url. Which brings the one thing to keep in mind: **every page is a new Shiny session**. Nothing you compute on `/` is available on `/contact`. That is the point rather than a limitation — it forces the data flowing between pages to be explicit — but it means state has to live somewhere shared: a cookie, a database, a disk cache. ## Something on every page Anything passed to `brochureApp()` that is not a `page()` or a `redirect()` is injected as it is into every page. That is where a stylesheet, a favicon or a `