Blog

Victor Campos

July 07, 2026

Spread the word


Share your thoughts

MatchBox includes a native web runtime for building small, fast BoxLang web applications without requiring a JVM or a traditional servlet container. You can follow the MatchBox open beta at https://github.com/ortus-boxlang/matchbox. There are two related pieces in the beta today: a webroot server for .bxm templates and static assets, and a routed app server built around web.server(). Both are early, but they show the direction clearly: BoxLang should be able to serve HTTP from a compact native runtime when the application does not need the full JVM stack.


🏗️ Two Ways to Serve

┌──────────────────────────────────────────────────────────────────┐
│                  MatchBox Native Web Runtime                      │
│                                                                   │
│  ┌─────────────────────────────┐  ┌──────────────────────────┐   │
│  │     Webroot Mode            │  │    App Server Mode       │   │
│  │  matchbox --serve           │  │    web.server()          │   │
│  │                             │  │                          │   │
│  │  - .bxm template files      │  │  - Explicit routing      │   │
│  │  - Static asset serving     │  │  - Middleware pipeline   │   │
│  │  - Familiar request scopes  │  │  - JSON APIs             │   │
│  │  - Quick start, no config   │  │  - WebSockets            │   │
│  │                             │  │  - Webhook helpers       │   │
│  └─────────────────────────────┘  └──────────────────────────┘   │
│                                                                   │
│       Built on: matchbox-server crate (Axum + Tokio)             │
└──────────────────────────────────────────────────────────────────┘

📄 Webroot and BXM Templates

The webroot server is the quickest path to get BoxLang serving HTTP. Point MatchBox at a directory and it serves .bxm files plus static assets:

matchbox --serve --port 8080 --webroot ./www

BXM files are HTML-like templates that MatchBox transpiles ahead of time into BoxLang bytecode. A template such as:

<bx:output>Hello #user.name#!</bx:output>

is lowered into normal output calls that the VM executes efficiently. The same .bxm templating language you know from BoxLang JVM works here - interpolation with #, <bx:output>, <bx:if>, <bx:loop>, includes, and all the standard template tags.

The webroot runtime injects familiar request scopes into each request:

┌────────────────────────────────────────────────────────────┐
│               Injected Request Scopes                       │
├──────────────┬─────────────────────────────────────────────┤
│ url          │ Query string parameters                      │
│ form         │ POST body fields                             │
│ cookie       │ Request cookies                              │
│ session      │ In-memory session state                      │
│ cgi          │ Server and request metadata                  │
└──────────────┴─────────────────────────────────────────────┘

The repo includes a web server example with the following pages:

  • index.bxm - session persistence and dynamic output
  • about.bxm - CGI scope and loops
  • contact.bxm - URL parameters and conditional logic
  • styles.css - served as a static asset alongside templates

There is also a starter template to scaffold a new project:

https://github.com/ortus-boxlang/matchbox-web-server-template


🛣️ Routed Apps with web.server()

For applications that need explicit routing, middleware, APIs, or webhooks, the app server exposes a clean BoxLang API:

import boxlang.web

app = web.server()

app.get( "/api/hello/:name", ( event, rc, prc ) -> {
    event.renderJson( {
        "message": "Hello " & rc.name
    } )
} )

app.listen( 8090 )

The Request Collections

Every route handler receives three arguments:

┌──────────────────────────────────────────────────────────────────┐
│                    Handler Arguments                              │
├──────────────┬───────────────────────────────────────────────────┤
│ event        │ Request and response helpers (render, redirect...) │
├──────────────┼───────────────────────────────────────────────────┤
│ rc           │ Public request collection:                         │
│              │   - Route params  (:name, :id, etc.)              │
│              │   - Query string params                            │
│              │   - Form fields                                    │
│              │   - Top-level JSON body keys                       │
├──────────────┼───────────────────────────────────────────────────┤
│ prc          │ Private request collection:                        │
│              │   - Middleware-set values                          │
│              │   - Internal state not exposed to the client       │
└──────────────┴───────────────────────────────────────────────────┘

Middleware

Middleware uses a fourth next argument to build request pipelines:

app.use( ( event, rc, prc, next ) -> {
    prc.requestStarted = true
    next.run()
} )

What the App Server Supports Today

┌────────────────────────────────────────────────────────────┐
│           Native App Server Capabilities (Beta)            │
├────────────────────────────────────────┬───────────────────┤
│ Route groups                           │ ✅                │
│ Middleware pipeline                    │ ✅                │
│ Cookies                                │ ✅                │
│ In-memory sessions                     │ ✅                │
│ JSON responses (renderJson)            │ ✅                │
│ HTML responses (renderHtml)            │ ✅                │
│ Static asset mounts                    │ ✅                │
│ Explicit template rendering            │ ✅                │
│ Signed webhook helpers                 │ ✅                │
│ WebSocket listeners                    │ ✅                │
└────────────────────────────────────────┴───────────────────┘

🔌 WebSockets

The beta also includes a WebSocket listener model built around lifecycle methods. Listener classes define:

class MySocketListener {

    function onConnect( channel ) {
        channel.sendText( "Welcome!" )
    }

    function onMessage( message, channel ) {
        channel.broadcast( "Echo: " & message )
    }

    function onClose( channel ) {
        // cleanup
    }

}

Channels support sending text, JSON, bytes, broadcasting to all connected clients, and explicit close operations. That gives MatchBox a path for small real-time apps, live dashboards, and collaborative experiments - without pulling in a large server stack.

┌──────────────────────────────────────────────────────────────────┐
│                    WebSocket Channel API                          │
│                                                                   │
│  channel.sendText( message )    - Send a text frame              │
│  channel.sendJson( struct )     - Serialize and send JSON        │
│  channel.sendBytes( binary )    - Send raw bytes                 │
│  channel.broadcast( message )   - Send to all connected clients  │
│  channel.close()                - Close the connection           │
└──────────────────────────────────────────────────────────────────┘

🧱 Under the Hood

The native web server is powered by the matchbox-server crate, which is built on Axum and Tokio - Rust's most battle-tested async web infrastructure. Your BoxLang application code runs on top of that, with the fiber scheduler handling concurrency at the VM level.

┌──────────────────────────────────────────────────────────────────┐
│                    MatchBox Server Stack                           │
│                                                                   │
│   BoxLang Application Code (.bxs / .bxm)                         │
│              │                                                    │
│              ▼                                                    │
│   MatchBox VM (fiber scheduler, bytecode execution)               │
│              │                                                    │
│              ▼                                                    │
│   matchbox-server crate                                           │
│              │                                                    │
│              ▼                                                    │
│   Axum  (HTTP routing, middleware, WebSockets)                    │
│              │                                                    │
│              ▼                                                    │
│   Tokio (async I/O runtime)                                       │
└──────────────────────────────────────────────────────────────────┘

No JVM. No servlet container. No Undertow or Jetty. The whole stack ships as a single compact binary.


🔍 Where This Fits

MatchBox web is not trying to replace the BoxLang JVM ecosystem. ColdBox, CommandBox, servlet containers, and the JVM runtime remain the mature path for full-stack production applications that need the complete ecosystem.

┌──────────────────────────────────────────────────────────────────┐
│              Which Runtime for Which Use Case?                    │
├──────────────────────────────┬───────────────────────────────────┤
│ MatchBox Native Web          │ BoxLang JVM (ColdBox / MiniServer)│
├──────────────────────────────┼───────────────────────────────────┤
│ Small APIs                   │ Full-stack MVC applications        │
│ Lightweight microservices    │ Enterprise apps with Java interop  │
│ Webhook receivers            │ ColdFusion CFML compatibility      │
│ Edge-style apps              │ Full module ecosystem (ForgeBox)   │
│ Static + dynamic pages       │ Complex ORM / datasources          │
│ WebSocket experiments        │ Production-hardened deployments    │
│ Native binary deployment     │ Servlet container integrations     │
│ Tiny container images        │                                    │
└──────────────────────────────┴───────────────────────────────────┘

⚠️ Beta Boundaries

This is open beta software. Some APIs may change as the app-server surface hardens.

One important distinction from the ESP32 embedded web profile: the native server has significantly more capability than what is available on a microcontroller. On ESP32, MatchBox intentionally supports a smaller route-driven profile and rejects heavier features at compile time. A web app that works on the native server may need to be simplified before it can run on a device.


🚀 Where to Start

Option 1: Webroot with BXM templates

# Scaffold from the starter template
git clone https://github.com/ortus-boxlang/matchbox-web-server-template myapp
cd myapp

# Serve it
matchbox --serve --port 8080 --webroot ./www

Option 2: Explicit routes with web.server()

// app.bxs
import boxlang.web

app = web.server()

app.get( "/", ( event, rc, prc ) -> {
    event.renderHtml( "<h1>Hello from MatchBox</h1>" )
} )

app.get( "/api/status", ( event, rc, prc ) -> {
    event.renderJson( { "ok": true, "runtime": "matchbox" } )
} )

app.listen( 8080 )
matchbox app.bxs

Use the webroot mode for dynamic BXM pages and server-rendered content. Use web.server() when you want explicit routes, JSON endpoints, middleware, or WebSockets.

The interesting part is not just that MatchBox can serve HTTP. It is that BoxLang can now target a compact native web runtime, with the same language moving between scripts, CLI tools, servers, browser bundles, and devices.


🔭 The Bigger Picture

┌──────────────────────────────────────────────────────────────────┐
│                    BoxLang Runtime Landscape                       │
│                                                                   │
│  ┌───────────────────────┐    ┌─────────────────────────────┐    │
│  │   BoxLang JVM Runtime │    │     MatchBox (Rust VM)      │    │
│  │                       │    │                             │    │
│  │  - Web Servers        │    │  - Native Web  ◄── Here    │    │
│  │  - AWS Lambda         │    │  - Browser (WASM/JS)        │    │
│  │  - Google Cloud Fns   │    │  - WASI Containers          │    │
│  │  - Desktop (Electron) │    │  - Edge Runtimes            │    │
│  │  - Full Java interop  │    │  - Native CLI               │    │
│  │  - All BL modules     │    │  - ESP32 / IoT              │    │
│  └───────────────────────┘    └─────────────────────────────┘    │
│                                                                   │
│           Same BoxLang language. Different runtimes.              │
└──────────────────────────────────────────────────────────────────┘

Explore the project and open issues at https://github.com/ortus-boxlang/matchbox.

Read the full MatchBox docs at https://boxlang.ortusbooks.com/boxlang-framework/matchbox.


Join the Ortus Community

Be part of the movement shaping the future of web development. Stay connected and receive the latest updates on product launches, tool updates, promo services and much more.

Subscribe to our newsletter for exclusive content.

Follow Us on Social media and don't miss any news and updates:

Add Your Comment

Recent Entries

Open at the Core. Ready for Production: BoxLang

Open at the Core. Ready for Production: BoxLang

Open source should give developers freedom not push them into a corner when an application becomes successful.

That principle shaped one of the most important segments of the Into the Box 2026 Day 1 keynote: the continued evolution of BoxLang+, BoxLang++, and the growing ecosystem of professional modules surrounding the language.

Maria Jose Herrera
Maria Jose Herrera
August 20, 2026
BoxLang in Motion: Modern Web App Development

BoxLang in Motion: Modern Web App Development

The Day 1 keynote at Into the Box 2026 was not simply a list of new BoxLang features.

It showed what happens when a language, compiler, runtime, deployment model, and developer ecosystem evolve together around one goal: helping teams build modern applications without unnecessary complexity.

Victor Campos
Victor Campos
August 18, 2026
Introducing BoxLang AI Explorer: A Local Catalog for Every AI Pattern

Introducing BoxLang AI Explorer: A Local Catalog for Every AI Pattern

Learning a new AI API usually means jumping between scattered documentation pages, guessing at imports, and copy-pasting code that may or may not still work. We wanted something better for BoxLang AI, so we built the BoxLang AI Explorer: a local, browser-based catalog of runnable BoxLang AI examples, organized by category and difficulty, each with guidance, source code, and sample output.

Luis Majano
Luis Majano
August 14, 2026