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

Ortus & BoxLang June Recap 2026

Ortus & BoxLang June Recap 2026

July was packed with exciting advancements across the Ortus ecosystem, bringing new BoxLang releases, powerful developer tools, and continued innovation in AI and multi-runtime development.

Victor Campos
Victor Campos
July 06, 2026
Ortus Solutions and BoxLang at CFCamp 2026: Platinum Sponsor, Keynote Leaders, and a Full Lineup of Innovation

Ortus Solutions and BoxLang at CFCamp 2026: Platinum Sponsor, Keynote Leaders, and a Full Lineup of Innovation

CFCamp 2026 was an important milestone for the Ortus Solutions team and for the growing BoxLang ecosystem.

This year, Ortus Solutions participated as a Platinum Sponsor and had the honor of leading the official Keynote, where Luis Majano, Brad Wood, and Jacob Beers shared major updates around ColdBox, BoxLang, AI, and multi-runtime support.

The message was clear: the CFML ecosystem is not standing still. With BoxLang, ColdBox, C...

Cristobal Escobar
Cristobal Escobar
July 02, 2026
Into the Box 2026 Presentation Slides Are Now Available

Into the Box 2026 Presentation Slides Are Now Available

One of the best parts of Into the Box is that the learning doesn't end when the conference does.

We're excited to share that all official Into the Box 2026 presentation slides are now publicly available. Whether you attended the conference and want to revisit your favorite sessions or you're exploring the content for the first time, you can now browse the complete collection of presentation decks.

Victor Campos
Victor Campos
June 30, 2026