Beta documentation. This is an early preview — content is still in active development. Feedback helps shape the final release. Share your thoughts or join the discussion.

Twig Overview

Twig is a template engine. You write HTML with placeholders, and Twig fills them with real data. It's fast, secure, and designed for designers and developers...

On this page

What is Twig?

Twig is a template engine. You write HTML with placeholders, and Twig fills them with real data. It's fast, secure, and designed for designers and developers alike.

New to Twig? The Twig documentation is excellent. Wapka uses Twig 3.x with sandboxed execution — no PHP functions, no filesystem access, safe by default.

Two ways to create templates

Inline templates

Define in your Lua script with app:set_template():

app:set_template("hello", [[
<h1>{{ title }}</h1>
<p>{{ body }}</p>
]])

app:get("/", function(ctx)
    return ctx:render("hello", {
        title = "Welcome",
        body = "This page is rendered with Twig."
    })
end)

Database-backed templates

Store templates as pages (type=0) in your site. Edit them through the Wapka page editor — no code changes needed.

-- Renders the DB page named "index" as a Twig template
return ctx:render("index", { title = "Home" })

Templates in the database can use {% extends %}, {% include %}, and {% from %} to reference other pages.

Autoescape by page type

Twig auto-escapes output to prevent XSS attacks. The escaping strategy depends on the page type:

Page Type Twig Strategy Use for
0 (HTML) html Regular web pages
1 (Text) html Plain text documents
2 (CSS) css Stylesheets
3 (JS) js JavaScript files
4 (JSON) html JSON data
5 (XML) html XML documents

All types auto-escape by default. Use |raw only when you absolutely trust the content.

Passing data to templates

app:get("/profile/:username", function(ctx)
    local user = api.users.list({ search = ctx.params.username })
    if user.total == 0 then
        return ctx:error("User not found", 404)
    end

    return ctx:render("profile", {
        user = user.items[1],
        page_title = user.items[1].username,
        is_owner = env.is_user and api.users.me().id == user.items[1].id
    })
end)

A complete inline example

local app = framework()

app:set_template("layout", [[
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
    <header>My Site</header>
    {% block content %}{% endblock %}
    <footer>&copy; 2026</footer>
</body>
</html>
]])

app:set_template("home", [[
{% extends "layout" %}
{% block content %}
    <h1>{{ title }}</h1>
    <p>{{ body }}</p>
{% endblock %}
]])

app:get("/", function(ctx)
    return ctx:render("home", {
        title = "Welcome to My Site",
        body = "Built with Lua and Twig on Wapka."
    })
end)

Next: Twig Syntax — variables, loops, conditionals, and filters.

Next Twig Syntax