Add Alpine.js reactivity to your R web apps — without writing JavaScript.
Alpine.js handles small, local interactions through HTML attributes (x-data, x-show, x-on:click…). alpiner is an R wrapper that lets you attach those attributes to any htmltools tag from R, and works hand-in-hand with {htmxr} for the server-side round-trips.
Installation
pak::pak("hyperverse-r/alpiner")How it works
htmxr handles server interactions (a click sends an HTTP request, the response is swapped into the DOM). alpiner handles local interactions that never touch the server — toggles, counters, show/hide, form validation hints. Together they cover the full reactivity spectrum without a single line of JavaScript in your application code.
x_set() is the only primitive: it appends Alpine.js directives to an existing tag.
Example — local counter
A standalone counter, no server round-trip. The page is built with hx_page() from htmxr; Alpine is wired up via hx_head(x_script()).
library(htmxr)
library(alpiner)
#* @get /
#* @parser none
#* @serializer html
function() {
hx_page(
hx_head(x_script(), title = "Alpine.js Counter"),
tags$div(
tags$p(
tags$span("0") |> x_set(text = "count"),
style = "font-size: 3rem; font-weight: bold;"
),
tags$button(`@click` = "count++", "+"),
tags$button(`@click` = "count--", "-")
) |> x_set(data = "{ count: 0 }")
)
}Run it
x_run_example("counter")A second example, htmx, demonstrates combining alpiner (local state) with htmxr (server-driven content) in the same page.
Design philosophy
One primitive —
x_set()is enough. No wrappers, no DSL, no hidden state machine. You write Alpine.js, in R syntax.HTML over abstraction — Every
x_set()call appends standardx-*attributes to an htmltools tag. What you write in R is what lands in the browser.CSS-agnostic — No styling assumptions. Bring your own framework, or none.
Pairs with htmxr — Local state stays in the browser (Alpine.js). Anything that needs server logic goes through htmx. Two scopes, one mental model.
Code of Conduct
Please note that the alpiner project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.
