--- title: "Why htmxr?" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Why htmxr?} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = FALSE ) ``` > *htmxr does not replace Shiny — it answers different questions.* --- ## Shiny: the reference Before explaining what htmxr is, it is worth appreciating what Shiny achieved. Shiny democratized web application development for R users. It handles the browser-to-R communication invisibly, so data scientists can focus entirely on their analysis rather than web infrastructure. What Shiny does remarkably well: - **Reactive programming** — outputs update automatically when inputs change, through a dependency graph that Shiny manages for you - **R ↔ UI integration** — widgets, interactive plots, tables — everything lives in R - **Rapid prototyping** — a few lines of code give you a working app - **Ecosystem depth** — hundreds of packages (`shinydashboard`, `bslib`, `DT`, `plotly`...) built specifically for Shiny Shiny is the right tool for rich analytical dashboards, scientific interfaces, and internal data exploration tools. --- ## Different problems, different trade-offs Shiny and htmxr are built on fundamentally different communication models: | | Shiny | htmxr | |---|---|---| | Communication | WebSocket (persistent connection) | HTTP (request/response) | | Paradigm | Reactive graph | Explicit HTTP requests | | UI updates | Shiny decides what to reload | You target the DOM precisely | | State | R session per user | Database or URL | | Backend | R only | Any HTTP server | The practical difference: **in Shiny, your server reacts. In htmxr, your browser asks.** Shiny maintains one R session per connected user. That session holds all the reactive state — inputs, outputs, intermediate computations — and Shiny decides when to re-evaluate which outputs. This model is powerful and ergonomic, but it means each user consumes a persistent R process. htmxr apps are largely stateless. Each HTTP request is independent. The server computes something, returns an HTML fragment, and forgets. State lives in the database, the URL, or the client — not in a long-lived R session. --- ## Why choose htmxr? ### Surgical DOM updates Shiny reloads entire output blocks (`uiOutput`, `renderUI`) — sometimes more than strictly necessary. htmx updates **exactly** the targeted element, nothing more. The result is smoother interfaces, less visual flicker, and a faster perceived experience. Try the infinite scroll example to see this in practice — 53,940 diamonds loaded progressively, with only the next batch of cards appended to the DOM on each scroll event: ```{r} hx_run_example("infinity-scroll") ``` ### Scalability and infrastructure cost Shiny's persistent session model means memory consumption scales linearly with the number of connected users. A pool of shared plumber2 workers handles far more concurrent users on the same hardware. Deployment is standard: nginx, Docker, any VPS, any cloud platform. No Shiny Server license required. ### Native HTTP: cache, load balancers, SEO htmxr responses are plain HTML. This means: - **HTTP caching** — identical requests can be served instantly from a cache layer - **Horizontal load balancing** — no sticky sessions to manage, any worker can handle any request - **Search engine indexability** — content lives in the HTML, not generated client-side by JavaScript ### Progressive enhancement An htmxr app can work even when JavaScript is disabled — links and forms remain functional. You can enrich a static HTML page progressively, or add dynamic behaviour to an existing app without rewriting it from scratch. ### Interoperability htmxr generates standard HTML backed by a standard HTTP API. The same plumber2 endpoints that serve your htmxr frontend can be consumed by mobile apps, other services, or scripts in any language — without translation or adaptation. **This is particularly valuable when a proof-of-concept built in R needs to grow into a production system: the business logic stays in R, while other parts of the stack can call the same endpoints.** --- ## When to use each **Choose htmxr when:** - ✅ Public-facing apps with many concurrent users - ✅ Forms, CRUD interfaces, admin panels - ✅ SEO and indexability matter - ✅ Standard deployment (Docker, VPS, cloud) - ✅ You want to expose R logic to other services without rewriting it **Choose Shiny when:** - ✅ Rich analytical dashboards and scientific interfaces - ✅ Complex reactive logic with many interdependent outputs - ✅ Rapid prototyping for internal data exploration - ✅ Deep Shiny ecosystem integration (`DT`, `plotly`, `bslib`...) - ✅ You want R to own the full stack (no HTTP API needed) --- ## Summary htmxr is not a Shiny replacement. It is a different tool for different problems. If you need reactive, session-based dashboards in R, Shiny is the right choice. If you need scalable, HTTP-native apps that interoperate beyond R, htmxr is the answer.