Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 8 min read

Experience the Server Renaissance in Julia: Build Interactive Web Pages with WebForms Core

Julia is widely known for numerical computing, scientific programming, data analysis, and high-performance applications. But Julia can also be used to build web applications. With WebForms Core, Julia applications can m

Experience the Server Renaissance in Julia: Build Interactive Web Pages with WebForms Core

Julia is widely known for numerical computing, scientific programming, data analysis, and high-performance applications. But Julia can also be used to build web applications.

With WebForms Core, Julia applications can manipulate the browser UI from the server using server-side WebForms classes and WebForms commands.

The result is a different approach to interactive web development:

Julia Server β†’ WebForms β†’ Commands β†’ WebFormsJS β†’ HTML DOM

Instead of writing JavaScript for every UI operation, the server can generate commands that WebFormsJS executes in the browser.

Installation and Downloads

The Julia implementation of WebForms Core is provided as WebForms.jl, while the browser-side Executor is provided by WebFormsJS.

Download WebForms.jl

Download the Julia WebForms Core library directly from GitHub:

Download WebForms.jl

Then include the library in your Julia application:

include("WebForms.jl")

import .WebFormsCore
import .WebFormsCore: WebForms
import .WebFormsCore.InputPlace

Download WebFormsJS

WebFormsJS is the client-side JavaScript Executor responsible for executing WebForms commands and manipulating the HTML DOM.

Get WebFormsJS in npm

WebFormsJS Page in Elanat

You can also obtain the source directly from GitHub:

WebFormsJS on GitHub

Note: We also attempted to publish the WebForms Core package for Julia through the Julia General registry. However, the registry has strict requirements for package structure, documentation, testing, versioning, and release management, and we did not have the time required to meet all of these requirements for this project. For this reason, we decided not to continue with the registration process. WebForms.jl will remain available directly from its GitHub repository, where Julia developers can download and use it.

In the examples in this article, web-forms.js is served by the Julia application through HTTP.jl:

if req.target == "/script/web-forms.js"
    js = read(
        joinpath(@__DIR__, "script", "web-forms.js"),
        String
    )

    return HTTP.Response(
        200,
        ["Content-Type" => "text/javascript"],
        js
    )
end

The web server used throughout the examples is HTTP.jl:

using HTTP

HTTP.serve(
    handle_request,
    "127.0.0.1",
    8080
)

This gives the application a simple architecture:

Julia + HTTP.jl
       β”‚
       β–Ό
   WebForms.jl
       β”‚
       β–Ό
 WebForms Commands
       β”‚
       β–Ό
   WebFormsJS
       β”‚
       β–Ό
    HTML DOM

WebForms Core for Julia

The Julia implementation of WebForms Core provides the WebForms API directly inside Julia applications.

WebForms Core in Julia

A basic application can use Julia's HTTP package as its HTTP server:

using HTTP

include("WebForms.jl")

import .WebFormsCore
import .WebFormsCore: WebForms
import .WebFormsCore.InputPlace

The WebForms module provides the server-side API for creating and manipulating WebForms commands.

For example:

form = WebForms.Form()

WebForms.set_font_size(form, InputPlace.tag("form"), font_size)
WebForms.set_background_color(form, InputPlace.tag("form"), background_color)
WebForms.set_disabled(form, InputPlace.name("btn_SetBodyValue"), true)

WebForms.add_tag(form, InputPlace.tag("form"), "h3")
WebForms.set_text(form, InputPlace.tag("h3"), "Welcome $(name)!")

These operations do not directly manipulate the browser DOM from Julia.

Instead, they construct WebForms commands.

WebFormsJS then receives those commands and executes them in the browser.

A Complete Julia Example

Consider a simple page where the user enters a name, chooses a font size, and specifies a background color.

The HTML itself remains ordinary HTML:

html = """
<!DOCTYPE html>
<html>
<head>
  <title>Using WebForms Core</title>
  <script type="module" src="/script/web-forms.js"></script>
</head>
<body>
    <form method="post" action="/">
        <label for="txt_Name">Your Name</label>
        <input name="txt_Name" id="txt_Name" type="text" />
        <br>
        <label for="txt_FontSize">Set Font Size</label>
        <input name="txt_FontSize" id="txt_FontSize" type="number" value="16" min="10" max="36" />
        <br>
        <label for="txt_BackgroundColor">Set Background Color</label>
        <input name="txt_BackgroundColor" id="txt_BackgroundColor" type="text" />
        <br>
        <input name="btn_SetBodyValue" type="submit" value="Click to send data" />
    </form>
</body>
</html>
"""

When the form is submitted, Julia receives the request and processes the values:

body = String(req.body)
params = HTTP.queryparams(body)

if haskey(params, "btn_SetBodyValue")
    name = get(params, "txt_Name", "")
    background_color = get(params, "txt_BackgroundColor", "")
    font_size = parse(Int, get(params, "txt_FontSize", "16"))

    form = WebForms.Form()

    WebForms.set_font_size(
        form,
        InputPlace.tag("form"),
        font_size
    )

    WebForms.set_background_color(
        form,
        InputPlace.tag("form"),
        background_color
    )

    WebForms.set_disabled(
        form,
        InputPlace.name("btn_SetBodyValue"),
        true
    )

    WebForms.add_tag(
        form,
        InputPlace.tag("form"),
        "h3"
    )

    WebForms.set_text(
        form,
        InputPlace.tag("h3"),
        "Welcome $(name)!"
    )

    return HTTP.Response(
        200,
        WebForms.response(form)
    )
end

The important part is that the server does not need to return an entirely new HTML document.

It returns a WebForms response containing instructions for the browser.

The browser then executes those instructions through WebFormsJS.

Server-Orchestrated UI

This is the central idea behind WebForms Core.

The server determines what UI operation should happen, while WebFormsJS performs the actual browser-side execution.

For example:

Julia
  β”‚
  β”‚ WebForms commands
  β–Ό
WebForms
  β”‚
  β”‚ WebForms response
  β–Ό
WebFormsJS
  β”‚
  β”‚ DOM operations
  β–Ό
HTML DOM

This creates a Commander–Executor architecture.

The WebForms class acts as the server-side Commander.

WebFormsJS acts as the client-side Executor.

Julia therefore does not need to contain JavaScript implementations for every UI operation.

Interactive UI Without Writing JavaScript

WebForms Core can also define browser events from Julia.

Consider this page:

function html_form()
    return """
    <!DOCTYPE html>
    <html>
    <head>
        <title>WebForms Core Technology in Julia</title>
        <script type="module" src="/script/web-forms.js"></script>
    </head>
    <body>
        <h1>WebForms Core Technology in Julia</h1>
        <button id="Button1">Increase Textbox</button>
        <input type="number" id="Textbox1" value="40">
    </body>
    </html>
    """
end

The page contains an ordinary HTML button and input.

Now Julia can associate an event with that button:

form = WebForms.Form()

WebForms.set_comment_event(
    form,
    "Button1",
    HtmlEvent.OnClick,
    "incease"
)

The server can then define what should happen when the event occurs:

WebForms.start_index(form, "incease")

WebForms.increase_width(
    form,
    "Textbox1",
    Fetch.get_value("Textbox1")
)

The resulting WebForms instructions can be exported into HTML comments:

WebForms.export_to_html_comment(form)

The final response is:

return HTTP.Response(
    200,
    ["Content-Type" => "text/html; charset=utf-8"],
    html_form() *
    WebForms.export_to_html_comment(form)
)

WebFormsJS detects the WebForms instructions and executes them in the browser.

Fetching Browser Values

An important feature of this model is that commands can use values from the browser.

In the example:

Fetch.get_value("Textbox1")

represents the current value of the element.

That value can be used by another WebForms operation:

WebForms.increase_width(
    form,
    "Textbox1",
    Fetch.get_value("Textbox1")
)

This allows a sequence of server-defined UI operations to depend on browser state without requiring the Julia application to maintain a permanent mirror of the DOM.

HTML Remains HTML

One of the design goals of WebForms Core is to keep the HTML itself simple.

The page can remain:

<button id="Button1">Incease Textbox</button>
<input type="number" id="Textbox1" value="40">

There is no requirement to replace HTML with a component syntax.

The WebForms instructions can instead be transmitted separately or embedded as HTML comments.

This makes WebForms Core HTML-native.

Julia as the Server-Side UI Commander

The Julia application remains responsible for the server-side logic.

For example:

function handle_request(req::HTTP.Request)
    try
        if req.target == "/"
            form = WebForms.Form()

            WebForms.set_comment_event(
                form,
                "Button1",
                HtmlEvent.OnClick,
                "incease"
            )

            WebForms.start_index(form, "incease")

            WebForms.increase_width(
                form,
                "Textbox1",
                Fetch.get_value("Textbox1")
            )

            return HTTP.Response(
                200,
                ["Content-Type" => "text/html; charset=utf-8"],
                html_form() *
                WebForms.export_to_html_comment(form)
            )
        end

        return HTTP.Response(
            404,
            ["Content-Type" => "text/plain"],
            "Not Found"
        )

    catch e
        println("\n========== ERROR ==========")
        showerror(stdout, e, catch_backtrace())
        println("\n============================")
        println("REQUEST: ", req)

        return HTTP.Response(
            500,
            "Internal Server Error"
        )
    end
end

And the application can be started directly with:

HTTP.serve(
    handle_request,
    "127.0.0.1",
    8080
)

There is no separate frontend application required for this example.

WebForms Core and WebFormsJS

The Julia library is the server-side part of the technology.

The browser-side execution is performed by web-forms.js.

A Julia application can simply serve the JavaScript file:

if req.target == "/script/web-forms.js"
    js = read(
        joinpath(@__DIR__, "script", "web-forms.js"),
        String
    )

    return HTTP.Response(
        200,
        ["Content-Type" => "text/javascript"],
        js
    )
end

This separation is intentional.

The server-side WebForms implementation can be written in Julia, while the same WebFormsJS Executor can execute commands generated by WebForms implementations in different programming languages.

A Cross-Language Architecture

This makes WebForms Core different from a framework that couples a particular frontend runtime to a particular backend language.

The architecture is based on a protocol and an Executor:

Julia
C#
PHP
Python
R
Ruby
Go
JavaScript
Rust
Java
Elixir
Perl
Dart
C
C++
...
 β”‚
 β–Ό
WebForms
 β”‚
 β–Ό
WebForms Commands
 β”‚
 β–Ό
WebFormsJS
 β”‚
 β–Ό
HTML DOM

The server-side implementation can therefore be native to the programming language.

The browser does not need to know which programming language generated the commands.

Why Julia?

Julia already provides a powerful ecosystem for scientific and technical computing.

With WebForms Core, the same language can also participate in server-side interactive web applications while retaining its existing HTTP ecosystem.

A Julia application can therefore combine:

  • Julia application logic
  • HTTP.jl
  • WebForms Core
  • WebFormsJS
  • standard HTML

without requiring a separate JavaScript application to implement every interactive operation.

Stateless Server-Orchestrated UI

WebForms Core is designed around server-side commands rather than maintaining a server-side copy of the browser DOM.

The server receives a request, executes its logic, and generates commands.

The browser executes those commands.

Conceptually:

HTTP Request
     β”‚
     β–Ό
Julia Server
     β”‚
     β–Ό
WebForms Commands
     β”‚
     β–Ό
HTTP Response
     β”‚
     β–Ό
WebFormsJS
     β”‚
     β–Ό
Browser DOM

The server does not need to maintain a persistent component tree representing the browser.

This makes the approach suitable for applications that prefer stateless HTTP request processing.

WebForms Core in Julia

The Julia implementation demonstrates that WebForms Core is not tied to a single programming language.

A Julia developer can write:

form = WebForms.Form()

WebForms.set_font_size(
    form,
    InputPlace.tag("form"),
    20
)

WebForms.set_background_color(
    form,
    InputPlace.tag("form"),
    "lightblue"
)

WebForms.set_text(
    form,
    InputPlace.tag("h3"),
    "Welcome Julia!"
)

and let WebFormsJS translate those server-generated commands into browser-side DOM operations.

That is the fundamental idea of Server-Orchestrated UI:

The server decides what should happen. The client executes it.

With WebForms Core, Julia can participate in that architecture while keeping the application logic on the server and the browser interface based on ordinary HTML and WebFormsJS.

Related links

In Elanat:

in GitHub:

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.