boxlang-templating
BoxLang Templating Language
Overview
BoxLang's templating language uses .bxm files (BoxLang Markup) to mix HTML with
dynamic server-side code. The default mode in .bxm files is HTML output — you
embed BoxLang logic using <bx:*> tags and output expressions with #expression#.
File Types Recap
| Extension | Default mode | Primary use |
|---|---|---|
.bx |
Script | Classes, services, models |
.bxs |
Script | Standalone scripts, CLI tools |
.bxm |
Tag/markup | Templates, views, HTML pages |
Output Expression Syntax
Use #expression# to interpolate values. The expression is evaluated and output
is HTML-escaped automatically inside <bx:output>:
<bx:output>
<h1>Hello, #user.name#!</h1>
<p>Today is #dateFormat( now(), "long" )#</p>
<p>Items: #order.items.len()#</p>
</bx:output>
Always wrap output in <bx:output> — without it, #variable# is treated
as a literal string and not evaluated:
<!-- BAD: #name# is printed as literal text, not evaluated -->
<p>#name#</p>
<!-- GOOD: #name# is evaluated and output -->
<bx:output><p>#name#</p></bx:output>
Core Template Components
<bx:output> — Render Dynamic Content
<bx:output>
<p>User: #user.firstName# #user.lastName#</p>
<p>Email: #encodeForHTML( user.email )#</p>
</bx:output>
Options:
encodeFor="html"— auto-encode all expressions (recommended for untrusted data)
<!-- Auto-encode all output in this block -->
<bx:output encodeFor="html">
<p>#userSuppliedContent#</p>
</bx:output>
<bx:set> — Declare Variables
<bx:set var="greeting" value="Hello, #user.name#!">
<bx:set var="items" value="#productService.getFeatured()#">
<bx:set var="count" value="#items.len()#">
<bx:if> / <bx:elseif> / <bx:else> — Conditionals
<bx:if condition="#user.isLoggedIn#">
<p>Welcome back, #encodeForHTML( user.name )#!</p>
<bx:elseif condition="#session.hasGuideToken#">
<p>Continue as guest</p>
<bx:else>
<a href="/login">Please log in</a>
</bx:if>
<bx:loop> — Iteration
Array loop:
<bx:loop array="#products#" item="product">
<div class="product">
<h3><bx:output>#encodeForHTML( product.name )#</bx:output></h3>
<p><bx:output>$#numberFormat( product.price, "0.00" )#</bx:output></p>
</div>
</bx:loop>
Struct loop:
<bx:loop struct="#config#" item="value" key="key">
<bx:output><p>#key#: #value#</p></bx:output>
</bx:loop>
Query loop:
<bx:loop query="#users#">
<bx:output>
<tr>
<td>#users.id#</td>
<td>#encodeForHTML( users.name )#</td>
<td>#encodeForHTML( users.email )#</td>
</tr>
</bx:output>
</bx:loop>
Index / count loop:
<bx:loop from="1" to="#items.len()#" index="i">
<bx:output><li>#i#. #items[ i ].name#</li></bx:output>
</bx:loop>
<bx:include> — Include Partial Templates
<!-- Reuse header and footer partials -->
<bx:include template="/includes/header.bxm">
<main>
<!-- page content -->
</main>
<bx:include template="/includes/footer.bxm">
Pass variables to the included template via the current scope (variables are inherited by default in includes).
<bx:script> — Inline Script Blocks
Switch to script mode within a template:
<bx:script>
var products = productService.getFeatured( limit=6 )
var totalPages = ceiling( products.recordCount / 10 )
</bx:script>
<bx:loop array="#products#" item="p">
<bx:output><div>#p.name#</div></bx:output>
</bx:loop>
<bx:switch> / <bx:case> — Switch Statements
<bx:switch expression="#user.role#">
<bx:case value="admin">
<bx:include template="/views/admin-dashboard.bxm">
</bx:case>
<bx:case value="editor">
<bx:include template="/views/editor-dashboard.bxm">
</bx:case>
<bx:defaultcase>
<bx:include template="/views/user-dashboard.bxm">
</bx:defaultcase>
</bx:switch>
<bx:try> / <bx:catch> — Error Handling in Templates
<bx:try>
<bx:set var="data" value="#remoteService.getData()#">
<bx:output><p>#data.message#</p></bx:output>
<bx:catch type="any" variable="e">
<p class="error">Could not load data: <bx:output>#encodeForHTML( e.message )#</bx:output></p>
</bx:catch>
</bx:try>
Mixing Script and Tag Syntax
You can freely mix script blocks and tag components in .bxm files:
<bx:script>
// Load data using script syntax
var pageTitle = "Product Catalog"
var categories = categoryService.getAll()
var featuredIds = url.keyExists( "cat" ) ? [ url.cat ] : []
</bx:script>
<!DOCTYPE html>
<html lang="en">
<head>
<bx:output><title>#encodeForHTML( pageTitle )#</title></bx:output>
</head>
<body>
<nav>
<bx:loop array="#categories#" item="cat">
<bx:output>
<a href="/catalog?cat=#encodeForURL( cat.slug )#"
class="#featuredIds.contains( cat.id ) ? 'active' : ''#">
#encodeForHTML( cat.name )#
</a>
</bx:output>
</bx:loop>
</nav>
</body>
</html>
Layout / View Patterns
Nested Includes (Layout Pattern)
<!-- views/layout.bxm -->
<!DOCTYPE html>
<html lang="en">
<head>
<bx:output><title>#pageTitle ?: "My App"#</title></bx:output>
<link rel="stylesheet" href="/css/app.css">
</head>
<body>
<bx:include template="/views/partials/nav.bxm">
<main>
<bx:include template="#contentTemplate#">
</main>
<bx:include template="/views/partials/footer.bxm">
</body>
</html>
<!-- In a page handler/template -->
<bx:set var="pageTitle" value="Dashboard">
<bx:set var="contentTemplate" value="/views/dashboard-content.bxm">
<bx:include template="/views/layout.bxm">
HTML Output Encoding Reference
Always encode user-supplied data before rendering:
<bx:output>
<!-- HTML context — encode entities -->
<p>#encodeForHTML( userBio )#</p>
<!-- Attribute context -->
<input value="#encodeForHTMLAttribute( formValue )#">
<!-- URL context -->
<a href="/profile?u=#encodeForURL( username )#">View Profile</a>
<!-- JavaScript context -->
<script>
const name = "#encodeForJavaScript( displayName )#";
</script>
</bx:output>
Query of Queries in Templates
Use <bx:query> for database queries directly in templates (acceptable for
simple templates; prefer service layer for complex logic):
<bx:script>
var users = queryExecute(
"SELECT id, name, email FROM users WHERE active = :active ORDER BY name",
{ active: { value: true, cfsqltype: "cf_sql_bit" } }
)
</bx:script>
<table>
<thead><tr><th>Name</th><th>Email</th></tr></thead>
<tbody>
<bx:loop query="#users#">
<bx:output>
<tr>
<td>#encodeForHTML( users.name )#</td>
<td>#encodeForHTML( users.email )#</td>
</tr>
</bx:output>
</bx:loop>
</tbody>
</table>
Common Mistakes to Avoid
| Mistake | Fix |
|---|---|
#var# outside <bx:output> |
Wrap in <bx:output> |
| Raw user data in output | Use encodeForHTML() or encodeFor="html" |
| Logic-heavy templates | Move to service layer; keep templates presentational |
| Missing closing tags | <bx:if> requires </bx:if>, <bx:loop> requires </bx:loop> |
| Unscoped variables | Declare with <bx:set> or <bx:script> var statements |
| Including with absolute OS paths | Use web-root-relative paths: /views/... |
More from ortus-boxlang/skills
boxlang-functional-programming
Use this skill when working with BoxLang lambdas, closures, arrow functions, higher-order functions, functional array/struct pipelines (map, filter, reduce, flatMap, groupBy, etc.), destructuring, or spread syntax.
10boxlang-code-reviewer
Use this skill when reviewing BoxLang code for quality, correctness, security vulnerabilities, performance issues, style violations, or when providing structured code review feedback following BoxLang best practices and security guidelines.
9boxlang-best-practices
Use this skill when writing, reviewing, or improving BoxLang code to ensure it follows community best practices for naming, structure, scoping, error handling, performance, and maintainability.
9boxlang-classes-and-oop
Use this skill when writing BoxLang classes, components, interfaces, inheritance hierarchies, annotations, properties, constructors, or applying object-oriented design patterns in BoxLang.
9boxlang-web-development
Use this skill when building BoxLang web applications: Application.bx lifecycle, request/response handling, sessions, forms, REST APIs, HTTP clients, routing, CSRF protection, Server-Sent Events, or configuring CommandBox/MiniServer.
8boxlang-configuration
Use this skill when configuring BoxLang runtime settings via boxlang.json, setting environment variables for config overrides, configuring datasources, caches, executors, modules, logging, security, or schedulers — or when helping someone understand the BoxLang configuration system.
8