WebForms Core (WFC) is now available for R, bringing server-side UI manipulation and server-orchestrated browser interaction to the R programming language.
WebForms Core is a Server-Driven UI technology built around a stateless server that does not dynamically render the UI. Its output is standard HTML without framework-specific attributes or tags. WebForms Core uses a compact INI-based format for communication between the server and browser and can be implemented in different web programming languages.
The webformscore package provides the R implementation of the WebForms class, allowing R applications to generate WebForms Core commands that are executed in the browser by WebFormsJS.
This makes it possible to build interactive web interfaces in R without creating a separate JavaScript application or manually writing JavaScript for UI behavior.
WebForms Core in R
WebForms Core uses a Commander–Executor architecture:
R Application
│
▼
WebForms Class
│
│ WebForms Core Commands
│
▼
WebFormsJS Browser Runtime
│
▼
HTML DOM
In an R application, the WebForms class — provided by the webformscore package — acts as the Commander. It constructs a sequence of WebForms Core commands that describe UI operations and interaction logic.
WebFormsJS runs in the browser as the Executor. It parses those commands and performs the corresponding operations on the HTML DOM.
The R application therefore does not need to directly manipulate the browser DOM with JavaScript. R is responsible for constructing the command sequence, while the browser runtime is responsible for executing it.
This also shows that WebForms Core is not tied to a particular server language. The same architectural concept can be implemented across different programming languages through their corresponding WebForms classes. In R, this allows R to participate directly in server-orchestrated web interfaces without requiring a separate front-end framework or a separate JavaScript application.
Installation
The webformscore package can be installed from CRAN:
install.packages("webformscore")
Then load it in an R application:
library(webformscore)
A web server such as httpuv can be used to expose the R application over HTTP:
library(httpuv)
library(webformscore)
The WebForms class is provided by the webformscore package, while WebFormsJS runs on the client side.
A Digital Clock with WFC
The following example creates a digital clock using R, httpuv, WebForms Core, and WebFormsJS.
The clock updates every second. The time is obtained through WebForms Core date values, formatted on the server-command side, and assigned to the HTML element.
No custom JavaScript is written for the clock.
library(httpuv)
library(webformscore)
html_form <- function() {
'
<!DOCTYPE html>
<html>
<head>
<title>WebForms Core Technology in R - Digital Clock Example</title>
<script type="module" src="/script/web-forms.js"></script>
<style>
body {
margin: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #111;
color: #fff;
font-family: Arial, sans-serif;
}
h1 {
margin-bottom: 30px;
font-size: 28px;
font-weight: normal;
}
#Clock {
padding: 30px 45px;
border: 2px solid #333;
border-radius: 12px;
background: #000;
color: #00ff66;
font-family: "Courier New", monospace;
font-size: 64px;
font-weight: bold;
letter-spacing: 6px;
box-shadow:
0 0 15px rgba(0, 255, 102, 0.25),
inset 0 0 20px rgba(0, 255, 102, 0.08);
text-shadow:
0 0 5px #00ff66,
0 0 15px rgba(0, 255, 102, 0.7);
}
</style>
</head>
<body>
<h1>WebForms Core Technology in R</h1>
<div id="Clock"></div>
</body>
</html>
'
}
app <- list(
call = function(req) {
if (req$REQUEST_METHOD == "GET" &&
req$PATH_INFO == "/script/web-forms.js") {
return(list(
status = 200L,
headers = list(
"Content-Type" = "application/javascript; charset=utf-8"
),
body = paste(
readLines("script/web-forms.js", warn = FALSE),
collapse = "\n"
)
))
}
if (req$REQUEST_METHOD == "GET" &&
req$PATH_INFO == "/") {
form <- WebForms$new()
form$add_save_value("clock-format", "{{Hour}}:{{Minute}}:{{Second}}")
form$replace_save_value("clock-format", "{{Hour}}", Fetch$date_hours)
form$replace_save_value("clock-format", "{{Minute}}", Fetch$date_minutes)
form$replace_save_value("clock-format", "{{Second}}", Fetch$date_seconds)
form$set_format_save_value("clock-format", "(^|:)(\\d)(?=:|$)", "$$10$2")
form$set_text("Clock", Fetch$save("clock-format"))
form$delay(1000)
form$go_to(1, 31536000)
return(list(
status = 200L,
headers = list(
"Content-Type" = "text/html; charset=utf-8"
),
body = paste0(
html_form(),
form$export_to_html_comment()
)
))
}
return(list(
status = 404L,
headers = list(
"Content-Type" = "text/plain"
),
body = "Not Found"
))
}
)
server <- startServer(
"127.0.0.1",
8080,
app
)
Screenshot of Digital Clock
Note on the script/web-forms.js Path
The script/web-forms.js path is relative to the R session's working directory. Make sure the file is available under this path when the server starts. You can check the working directory with getwd() or change it with setwd().
How It Works
The clock starts by creating a WebForms instance:
form <- WebForms$new()
A temporary saved value is then created for the clock format:
form$add_save_value("clock-format", "{{Hour}}:{{Minute}}:{{Second}}")
The placeholders are replaced using WebForms Core date values:
Fetch$date_hours
Fetch$date_minutes
Fetch$date_seconds
For example:
form$replace_save_value("clock-format", "{{Hour}}", Fetch$date_hours)
The set_format_save_value function applies (regex-based) formatting to the stored value:
form$set_format_save_value("clock-format", "(^|:)(\\d)(?=:|$)", "$$10$2")
The pattern (^|:)(\\d)(?=:|$) matches a single digit that appears either at the beginning of the string or immediately after a :, and is followed by either a : or the end of the string. Group 1 ($1) captures the start or the :, and group 2 ($2) captures the digit itself.
In the replacement string "$$10$2", the double dollar sign $$ escapes the dollar sign so it is not interpreted as direct access to a JavaScript object, such as $document. After this escaping, the replacement effectively becomes $1 + 0 + $2: it keeps the captured delimiter, inserts a literal 0, and then keeps the captured digit. This adds the leading zero required for a conventional digital clock.
For example, when the hour is 7, the result becomes:
07
while an hour such as 17 remains unchanged:
17
The resulting value is assigned to the Clock element:
form$set_text("Clock", Fetch$save("clock-format"))
The command sequence then waits for one second:
form$delay(1000)
and continues the execution:
form$go_to(1, 31536000)
WebFormsJS executes these commands in the browser, causing the displayed time to update continuously.
No Manual JavaScript
One of the important aspects of this example is what is not present.
There is no code such as:
setInterval(...)
There is no DOM manipulation such as:
document.getElementById(...)
There is no custom JavaScript clock implementation.
The only JavaScript loaded by the page is the WebFormsJS runtime:
<script type="module" src="/script/web-forms.js"></script>
The behavior of the clock is described through WebForms Core commands generated from R.
This demonstrates the distinction between the application language and the browser runtime.
R describes the behavior.
WebFormsJS executes the behavior.
Installing WebFormsJS
The latest WebFormsJS Executor is available through npm or as a downloadable JavaScript file.
Installation via Package
npm package: webformsjs
npm install webformsjs
Download / Copy the File
Why This Is Interesting for R
R is traditionally associated with statistical computing, data analysis, scientific computing, and research applications.
With WebForms Core, R can also be used to construct interactive browser interfaces using the same server-orchestrated UI model.
This can be useful for applications such as:
- Data analysis interfaces
- Scientific dashboards
- Research tools
- Interactive reports
- Internal applications
- Data-driven forms
- Administrative interfaces
- Real-time UI experiments
- Browser-based R applications
The important point is that the browser does not need to be treated as a completely separate application.
The server can orchestrate the interface through WebForms Core commands.
Conclusion
The digital clock is a small example, but it demonstrates an important capability: R can be used to construct browser UI behavior through WebForms Core without manually programming the browser in JavaScript.
The application uses R and the webformscore package to create the commands, while WebFormsJS provides the browser-side runtime that executes them.
R → WebForms → Commands → WebFormsJS → HTML DOM
This opens the door to using R not only as a data and computation language, but also as a server-side Commander for interactive web interfaces.
Related links
In Elanat:
in GitHub:


Top comments (0)