- Add complete dark mode system with theme context and toggle - Implement dark mode toggle component in navigation menu - Add client-side routing with SSR-safe signal handling - Fix language selector styling for better dark mode compatibility - Add documentation system with mdBook integration - Improve navigation menu with proper external/internal link handling - Add comprehensive project documentation and configuration - Enhance theme system with localStorage persistence - Fix arena panic issues during server-side rendering - Add proper TypeScript configuration and build optimizations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
9.3 KiB
Rustelo Template System
A powerful localized template system for Rustelo using Tera templates and TOML configuration files.
Overview
The Rustelo template system allows you to create dynamic pages using:
- Tera Templates: Flexible HTML templates with variables, filters, and logic
- TOML Configuration:
.tpl.tomlfiles that define template data and settings - Localization: Multi-language support with language-prefixed configuration files
- URL Routing: Clean URLs like
/page:content-namethat map to template configurations
How It Works
1. Template Files
Templates are HTML files with Tera syntax stored in the templates/ directory:
<!-- templates/blog-post.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<h1>{{title}}</h1>
<p>By {{author}} on {{published_date}}</p>
<div>{{content | markdown | safe}}</div>
</body>
</html>
2. Configuration Files
Configuration files are TOML files that specify which template to use and provide data:
# content/docs/en_my-blog-post.tpl.toml
template_name = "blog-post"
[values]
title = "My First Blog Post"
author = "John Doe"
published_date = "2024-01-15"
content = """
# Hello World
This is my first blog post using Rustelo's template system!
## Features
- Easy to use
- Localized content
- Flexible templating
"""
3. URL Mapping
The system maps URLs to configuration files using language prefixes:
- URL:
/page:my-blog-post?lang=en - Maps to:
content/docs/en_my-blog-post.tpl.toml - Uses template:
templates/blog-post.html
Directory Structure
rustelo/
├── templates/ # Tera template files
│ ├── blog-post.html
│ ├── page.html
│ └── layout.html
├── content/
│ └── docs/ # Template configuration files
│ ├── en_getting-started.tpl.toml
│ ├── es_getting-started.tpl.toml
│ ├── en_about.tpl.toml
│ └── fr_about.tpl.toml
└── server/src/template/ # Template system code
├── mod.rs
├── config.rs
├── engine.rs
├── loader.rs
├── service.rs
└── routes.rs
Quick Start
1. Create a Template
Create templates/my-page.html:
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<h1>{{title}}</h1>
<p>{{description}}</p>
{% if featured_image %}
<img src="{{featured_image}}" alt="{{title}}">
{% endif %}
<div class="content">
{{content | markdown | safe}}
</div>
{% if tags %}
<div class="tags">
{% for tag in tags %}
<span class="tag">{{tag}}</span>
{% endfor %}
</div>
{% endif %}
</body>
</html>
2. Create Configuration Files
Create content/docs/en_my-page.tpl.toml:
template_name = "my-page"
[values]
title = "Welcome to My Page"
description = "This is a sample page created with Rustelo templates"
featured_image = "/images/welcome.jpg"
content = """
# Welcome!
This page demonstrates the Rustelo template system.
## Features
- **Localization**: Multiple languages supported
- **Flexible**: Use any template with any data
- **Fast**: Cached rendering for performance
"""
tags = ["welcome", "demo", "rustelo"]
[metadata]
category = "sample"
author = "Your Name"
created_date = "2024-01-15"
Create content/docs/es_my-page.tpl.toml:
template_name = "my-page"
[values]
title = "Bienvenido a Mi Página"
description = "Esta es una página de ejemplo creada con plantillas Rustelo"
featured_image = "/images/welcome.jpg"
content = """
# ¡Bienvenido!
Esta página demuestra el sistema de plantillas de Rustelo.
## Características
- **Localización**: Múltiples idiomas soportados
- **Flexible**: Usa cualquier plantilla con cualquier dato
- **Rápido**: Renderizado en caché para rendimiento
"""
tags = ["bienvenida", "demo", "rustelo"]
[metadata]
category = "muestra"
author = "Tu Nombre"
created_date = "2024-01-15"
3. Access Your Page
- English:
http://localhost:3030/page:my-page?lang=en - Spanish:
http://localhost:3030/page:my-page?lang=es - Default:
http://localhost:3030/page:my-page(uses default language)
Configuration Reference
Template Configuration Format
# Required: Template file to use (without .html extension)
template_name = "blog-post"
# Required: Data to pass to the template
[values]
title = "Page Title"
content = "Page content in markdown"
author = "Author Name"
tags = ["tag1", "tag2"]
enable_comments = true
custom_data = { key = "value" }
# Optional: Metadata not passed to template
[metadata]
category = "blog"
seo_title = "Custom SEO Title"
seo_description = "Custom SEO Description"
Built-in Template Variables
The system automatically provides these variables to all templates:
template_name: The name of the template being usedsource_path: Path to the configuration filelang: Current language codemetadata: The metadata section from the configuration
Built-in Filters
markdown: Convert markdown to HTMLdate_format: Format datesslug: Convert text to URL-friendly slugexcerpt: Extract excerpt from textsafe: Mark content as safe HTML
Example usage:
{{content | markdown | safe}}
{{published_date | date_format(format="%B %d, %Y")}}
{{title | slug}}
{{description | excerpt(length=150)}}
Language Support
Language Fallback Chain
When requesting a page, the system follows this fallback chain:
- Requested language:
{lang}_{content-name}.tpl.toml - Default language:
{default_lang}_{content-name}.tpl.toml - No prefix:
{content-name}.tpl.toml
Configuration
let template_service = TemplateService::new("templates", "content/docs")?
.with_languages(vec!["en".to_string(), "es".to_string(), "fr".to_string()])
.with_default_language("en");
API Endpoints
Template Page Endpoints
GET /page/:content_name?lang=:lang- Serve template page as HTMLGET /api/template/:content_name?lang=:lang- Get template page as JSON
Management Endpoints
GET /api/template/list/:lang- List available content for languageGET /api/template/languages- Get available languagesGET /api/template/stats- Get template service statisticsPOST /api/template/cache/clear- Clear template cachePOST /api/template/reload- Reload templates from diskGET /api/template/exists/:content_name?lang=:lang- Check if template existsGET /api/template/config/:content_name?lang=:lang- Get template configurationGET /api/template/health- Template service health check
Advanced Features
Custom Filters
// Add custom filter to template service
template_service.add_filter("reverse", |value: &Value, _: &HashMap<String, Value>| {
let text = value.as_str().unwrap_or("");
Ok(Value::String(text.chars().rev().collect()))
})?;
Custom Functions
// Add custom function to template service
template_service.add_function("current_year", |_: &HashMap<String, Value>| {
Ok(Value::Number(2024.into()))
})?;
Template Inheritance
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
<!-- templates/page.html -->
{% extends "base.html" %}
{% block title %}{{title}} - {{site_name}}{% endblock %}
{% block content %}
<h1>{{title}}</h1>
<div>{{content | markdown | safe}}</div>
{% endblock %}
Performance Tips
- Enable Caching: Keep caching enabled in production
- Preload Templates: Use
preload_language()to cache templates at startup - Template Compilation: Templates are compiled once and cached
- Static Assets: Use proper static file serving for images and CSS
Development Workflow
- Create template HTML files in
templates/ - Create configuration files in
content/docs/ - Test with
?reload=trueto reload templates during development - Use the API endpoints to debug and inspect configurations
- Check template service health with
/api/template/health
Examples
See the included example files:
templates/blog-post.html- Blog post templatetemplates/page.html- General page templatecontent/docs/en_getting-started.tpl.toml- Getting started pagecontent/docs/es_getting-started.tpl.toml- Spanish getting started pagecontent/docs/en_about.tpl.toml- About page
Integration with Rustelo
The template system integrates seamlessly with Rustelo's existing features:
- Authentication: Use auth middleware to protect template routes
- Database: Store template metadata in database if needed
- Localization: Works with Rustelo's existing i18n system
- Caching: Leverages Rustelo's caching infrastructure
Troubleshooting
Template Not Found
- Check file naming:
{lang}_{content-name}.tpl.toml - Verify template file exists in
templates/ - Check template_name in configuration matches template filename
Rendering Errors
- Use
/api/template/config/:content_nameto inspect configuration - Check template syntax with Tera documentation
- Verify all required variables are provided in
[values]
Performance Issues
- Enable caching in production
- Use template preloading
- Monitor with
/api/template/stats
For more help, check the logs or use the health check endpoint.