---
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.
