SuperAPI AI Directory

boxlang-templating

Frontend & websites

View repository

Updated 10-16 07:44

About this skill

BoxLang Templating Language

BoxLang is the AI-native software productivity platform for building, modernizing and running applications, with developers and AI agents working together.

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>

For reusable partial templates (app/views/partials/*.bxm), make <bx:output> the wrapper around the rendered HTML block whenever interpolation appears in that block. Keep bx:param and bx:set declarations outside the output block.


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/...