Jinax Website Example
A server-rendered website using Jinax templates with custom filters, global functions, and template inheritance.
Application Code
# app.py
from datetime import datetime
from pathlib import Path
from flaxon import Flaxon
from flaxon.jinax import Jinax
app = Flaxon("website", debug=True)
# Configure Jinax templates
app.use_templates(Jinax("templates", auto_reload=True))
# Custom filter
jinax = app.jinax
def currency_filter(value, symbol="$"):
try:
amount = float(value)
return f"{symbol}{amount:,.2f}"
except (TypeError, ValueError):
return value
jinax.add_filter("currency", currency_filter)
# Custom function
def get_year():
return datetime.now().year
jinax.add_global("current_year", get_year)
# Routes
@app.get("/")
async def home(request):
products = [
{"id": 1, "name": "Flaxon T-Shirt", "price": 29.99, "in_stock": True},
{"id": 2, "name": "Flaxon Mug", "price": 14.99, "in_stock": True},
{"id": 3, "name": "Flaxon Sticker Pack", "price": 9.99, "in_stock": False},
{"id": 4, "name": "Flaxon Developer Guide", "price": 49.99, "in_stock": True},
]
return await request.render("home.html", {
"title": "Flaxon Store",
"products": products,
})
@app.get("/about")
async def about(request):
return await request.render("about.html", {
"title": "About Us",
"description": "Flaxon is a technology-neutral, async-first Python backend framework.",
"features": [
"Async-first ASGI architecture",
"Flask-style route decorators",
"Optional modular structure",
"Request validation",
"WebSocket support",
"Middleware stack",
"Readable debugger",
],
})
@app.get("/product/<int:product_id>")
async def product_detail(request, product_id: int):
products = [
{"id": 1, "name": "Flaxon T-Shirt", "price": 29.99, "in_stock": True, "description": "Premium cotton t-shirt with Flaxon logo."},
{"id": 2, "name": "Flaxon Mug", "price": 14.99, "in_stock": True, "description": "Ceramic mug with Flaxon branding."},
{"id": 3, "name": "Flaxon Sticker Pack", "price": 9.99, "in_stock": False, "description": "Pack of 5 Flaxon stickers."},
{"id": 4, "name": "Flaxon Developer Guide", "price": 49.99, "in_stock": True, "description": "Complete guide to building with Flaxon."},
]
product = next((p for p in products if p["id"] == product_id), None)
if not product:
return await request.render("404.html", {"title": "Product Not Found"}), 404
return await request.render("product.html", {
"title": product["name"],
"product": product,
})
Template Files
templates/base.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Flaxon{% endblock %}</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: #f8fafc; color: #0f172a; }
nav { background: #0f172a; color: #e2e8f0; padding: 1rem 2rem; display: flex; gap: 2rem; align-items: center; }
nav a { color: #e2e8f0; text-decoration: none; }
nav a:hover { color: #7dd3fc; }
nav .brand { font-weight: bold; font-size: 1.2rem; }
main { max-width: 1200px; margin: 2rem auto; padding: 0 2rem; }
footer { text-align: center; padding: 2rem; color: #94a3b8; border-top: 1px solid #e2e8f0; margin-top: 2rem; }
</style>
</head>
<body>
<nav>
<span class="brand">Flaxon</span>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>© {{ current_year() }} Flaxon. All rights reserved.</p>
</footer>
</body>
</html>
templates/home.html
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<h1>Welcome to the Flaxon Store</h1>
<p>Explore our collection of Flaxon merchandise and resources.</p>
<div class="grid">
{% for product in products %}
<div class="card">
<h3>{{ product.name }}</h3>
<p class="price">{{ product.price|currency("USD") }}</p>
{% if product.in_stock %}
<span class="in-stock">✓ In Stock</span>
{% else %}
<span class="out-of-stock">✗ Out of Stock</span>
{% endif %}
<br>
<a href="/product/{{ product.id }}" class="btn">View Details</a>
</div>
{% endfor %}
</div>
{% endblock %}
Key Concepts
- Template Inheritance: Base template with blocks
- Custom Filters: Currency formatting
- Global Functions: Current year
- Async Rendering: Request.render()