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