Flaxon 0.3.0 and Teloce-Py 0.3.0 are available on PyPI. Release instructions are maintained on this site; source links identify the framework snapshot. Check version and upgrade guidance.
Jinax Templates
Overview
Jinax is Flaxon's optional server-side template engine powered by Jinja2.
It provides modern HTML rendering while integrating seamlessly with Flaxon's async-first architecture.
Features
- Server-side HTML rendering
- Template inheritance
- Automatic HTML escaping
- Async rendering
- Custom filters
- Custom global functions
- Template caching
- Hot reloading during development
- Macros
- Includes
- Layouts
- Jinja2 template caching and configurable reload behavior
Installation
Install Flaxon with template support:
pip install flaxon[templates]
Setup
Configure Jinax with your application.
from flaxon import Flaxon
from flaxon.jinax import Jinax
app = Flaxon("website")
app.use_templates(
Jinax(
"templates",
auto_reload=True
)
)
Project Structure
A typical project looks like:
project/
├── app.py
├── templates/
│ ├── base.html
│ ├── home.html
│ ├── about.html
│ ├── contact.html
│ ├── macros.html
│ └── partials/
│ ├── navbar.html
│ └── footer.html
└── static/
├── css/
├── js/
└── images/
Rendering Templates
Templates are rendered using the request object.
@app.get("/")
async def home(request):
return await request.render(
"home.html",
{
"title": "Home",
"name": "World",
"items": [
"Routing",
"Templates",
"Validation"
]
}
)
Your First Template
Create:
templates/home.html
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>
Welcome {{ name }}!
</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>
Complete copy-paste application
Create app.py:
from flaxon import Flaxon
from flaxon.jinax import Jinax
app = Flaxon("jinax-example", debug=True)
app.use_templates(Jinax("templates", auto_reload=True))
@app.get("/")
async def home(request):
return await request.render("home.html", {
"title": "Jinax",
"items": ["Routing", "Validation", "Templates"],
})
Create templates/home.html:
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>{{ title }}</title></head>
<body><h1>{{ title }}</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
</body>
</html>
Run pip install "flaxon[templates]" and then flaxon run app:app --reload.
Jinax uses Jinja2 autoescaping for HTML templates. Keep database queries and
permission decisions in routes/services and pass prepared view data to templates.
Template Inheritance
Inheritance allows pages to share a common layout.
Base Template
templates/base.html
<!DOCTYPE html>
<html>
<head>
<title>
{% block title %}
Flaxon
{% endblock %}
</title>
</head>
<body>
<header>
{% block header %}
Default Header
{% endblock %}
</header>
<main>
{% block content %}
{% endblock %}
</main>
<footer>
{% block footer %}
Copyright © 2026
{% endblock %}
</footer>
</body>
</html>
Child Template
templates/home.html
{% extends "base.html" %}
{% block title %}
Home
{% endblock %}
{% block header %}
Welcome
{% endblock %}
{% block content %}
<h1>{{ heading }}</h1>
<p>{{ description }}</p>
{% endblock %}
Including Templates
Reusable components can be included.
{% include "partials/navbar.html" %}
<h1>Home</h1>
{% include "partials/footer.html" %}
Built-in Filters
Jinax includes many commonly used filters.
| Filter | Description |
|---|---|
capitalize |
Capitalize text |
lower |
Convert to lowercase |
upper |
Convert to uppercase |
title |
Title case |
trim |
Remove whitespace |
escape |
Escape HTML |
safe |
Mark content as safe |
json |
Convert to JSON |
length |
Count items |
reverse |
Reverse a sequence |
join |
Join list items |
replace |
Replace text |
default |
Default value |
first |
First item |
last |
Last item |
truncate |
Shorten text |
date |
Format dates |
datetime |
Format date and time |
currency |
Format currency |
Filter Examples
{{ name|capitalize }}
{{ username|lower }}
{{ price|currency("USD") }}
{{ description|truncate(100) }}
{{ tags|join(", ") }}
{{ created_at|datetime("%Y-%m-%d %H:%M") }}
Custom Filters
Create your own filters.
jinax = Jinax(
"templates"
)
def currency_filter(
value,
symbol="$"
):
return f"{symbol}{value:,.2f}"
jinax.add_filter(
"currency",
currency_filter
)
Using the filter:
<p>
Price:
{{ product.price|currency("$") }}
</p>
Global Functions
Global functions can be registered and used directly inside templates.
jinax = Jinax(
"templates"
)
def get_user(username):
return {
"name": username,
"email": f"{username}@example.com"
}
jinax.add_global(
"get_user",
get_user
)
Using the function:
{% set user = get_user("alice") %}
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
Global Variables
Global variables are available in every template.
jinax.add_global(
"site_name",
"Flaxon"
)
jinax.add_global(
"version",
"0.1.0"
)
Template:
<footer>
{{ site_name }}
Version {{ version }}
</footer>
Macros
Macros allow reusable template components.
Create:
templates/macros.html
{% macro render_card(title, content, color="blue") %}
<div class="card card-{{ color }}">
<h3>{{ title }}</h3>
<p>{{ content }}</p>
</div>
{% endmacro %}
Using the macro:
{% import "macros.html" as macros %}
{{ macros.render_card(
"Welcome",
"Hello from Jinax",
"green"
) }}
Control Statements
Jinax supports standard template control statements.
Loop:
<ul>
{% for product in products %}
<li>
{{ product.name }}
</li>
{% endfor %}
</ul>
Conditional:
{% if user %}
<h2>
Welcome {{ user.name }}
</h2>
{% else %}
<h2>
Welcome Guest
</h2>
{% endif %}
Async Rendering
Jinax fully supports asynchronous rendering.
@app.get("/dashboard")
async def dashboard(request):
users = await database.get_users()
return await request.render(
"dashboard.html",
{
"users": users
}
)
Hot Reloading
During development templates can automatically reload.
app.use_templates(
Jinax(
"templates",
auto_reload=True
)
)
Hot reloading should normally be disabled in production.
Template Caching
Enable template caching for production deployments.
jinax = Jinax(
"templates",
cache_size=100
)
Larger applications may increase the cache size.
Autoescaping
Jinax automatically escapes HTML output to reduce XSS risks.
Example:
{{ username }}
Output:
<script>alert("XSS")</script>
becomes
<script>alert("XSS")</script>
Safe HTML
Only mark trusted HTML as safe.
{{ article.body|safe }}
Avoid using safe with untrusted user input.
Static Files
Reference static assets inside templates.
<link
rel="stylesheet"
href="/static/css/style.css"
>
<script
src="/static/js/app.js"
></script>
Complete Example
from datetime import datetime
from flaxon import Flaxon
from flaxon.jinax import Jinax
app = Flaxon(
"website-demo"
)
app.use_templates(
Jinax(
"templates",
auto_reload=True
)
)
jinax = app.jinax
def currency(
value,
symbol="$"
):
return f"{symbol}{value:,.2f}"
jinax.add_filter(
"currency",
currency
)
def now():
return datetime.now().strftime(
"%Y-%m-%d %H:%M:%S"
)
jinax.add_global(
"now",
now
)
@app.get("/")
async def home(request):
products = [
{
"name": "Laptop",
"price": 999.99
},
{
"name": "Keyboard",
"price": 49.99
},
{
"name": "Mouse",
"price": 19.99
}
]
return await request.render(
"home.html",
{
"title": "Store",
"products": products
}
)
Example template:
templates/home.html
{% extends "base.html" %}
{% block title %}
{{ title }}
{% endblock %}
{% block content %}
<h1>
Welcome to our Store
</h1>
<div class="products">
{% for product in products %}
<div class="product">
<h3>
{{ product.name }}
</h3>
<p>
{{ product.price|currency("$") }}
</p>
</div>
{% endfor %}
</div>
<p>
Generated:
{{ now() }}
</p>
{% endblock %}
Security
Jinax enables HTML autoescaping by default.
Recommended practices:
- Keep autoescaping enabled.
- Never trust user-generated HTML.
- Only use the
safefilter with trusted content. - Validate all user input.
- Use Content Security Policy (CSP) where appropriate.
- Sanitize uploaded HTML before rendering.
Performance Tips
For production deployments:
- Enable template caching.
- Disable hot reloading.
- Reuse template environments.
- Cache expensive database queries.
- Minimize complex template logic.
- Perform heavy processing inside Python instead of templates.
Debugging
When Flaxon runs in debug mode, template errors appear in the Debug Dashboard.
Open:
http://localhost:8000/__debug__
The debugger records:
- Template syntax errors
- Missing templates
- Undefined variables
- Rendering exceptions
- Stack traces
- Request information
- Error history
Sensitive information is automatically redacted.
Best Practices
- Keep business logic inside Python.
- Keep templates focused on presentation.
- Use template inheritance.
- Reuse components with macros and includes.
- Organize templates into folders.
- Prefer descriptive template names.
- Enable caching in production.
- Use async rendering when loading data.
Recommended Project Structure
project/
├── app.py
├── templates/
│ ├── base.html
│ ├── home.html
│ ├── about.html
│ ├── contact.html
│ ├── macros.html
│ ├── layouts/
│ ├── partials/
│ │ ├── navbar.html
│ │ ├── sidebar.html
│ │ └── footer.html
│ ├── auth/
│ ├── admin/
│ ├── errors/
│ └── emails/
└── static/
├── css/
├── js/
├── fonts/
└── images/
API Reference
See the Jinax API Reference for complete documentation of:
- Jinax
- Template rendering
- Filters
- Globals
- Macros
- Async rendering
- Template caching
- Autoescaping
Next Steps
Continue with:
- Authentication
- Databases
- Security
- Performance
- Debugging
- GraphQL
- Deployment
- Architecture
Use this capability in a full-stack app
Flaxon serves Python APIs and Teloce interfaces in one project. Keep validation, authorization and privileged operations on the server; components call those endpoints and present their results. Follow the full-stack lessons and Teloce integration reference to connect this capability to pages, components and application modules.