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 outputabout.bxm- CGI scope and loopscontact.bxm- URL parameters and conditional logicstyles.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