Rustelo/info/template_readme.md
Jesús Pérex 2f0f807331 feat: add dark mode functionality and improve navigation system
- 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>
2025-07-11 20:53:20 +01:00

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.toml files that define template data and settings
  • Localization: Multi-language support with language-prefixed configuration files
  • URL Routing: Clean URLs like /page:content-name that 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 used
  • source_path: Path to the configuration file
  • lang: Current language code
  • metadata: The metadata section from the configuration

Built-in Filters

  • markdown: Convert markdown to HTML
  • date_format: Format dates
  • slug: Convert text to URL-friendly slug
  • excerpt: Extract excerpt from text
  • safe: 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:

  1. Requested language: {lang}_{content-name}.tpl.toml
  2. Default language: {default_lang}_{content-name}.tpl.toml
  3. 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 HTML
  • GET /api/template/:content_name?lang=:lang - Get template page as JSON

Management Endpoints

  • GET /api/template/list/:lang - List available content for language
  • GET /api/template/languages - Get available languages
  • GET /api/template/stats - Get template service statistics
  • POST /api/template/cache/clear - Clear template cache
  • POST /api/template/reload - Reload templates from disk
  • GET /api/template/exists/:content_name?lang=:lang - Check if template exists
  • GET /api/template/config/:content_name?lang=:lang - Get template configuration
  • GET /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

  1. Enable Caching: Keep caching enabled in production
  2. Preload Templates: Use preload_language() to cache templates at startup
  3. Template Compilation: Templates are compiled once and cached
  4. Static Assets: Use proper static file serving for images and CSS

Development Workflow

  1. Create template HTML files in templates/
  2. Create configuration files in content/docs/
  3. Test with ?reload=true to reload templates during development
  4. Use the API endpoints to debug and inspect configurations
  5. Check template service health with /api/template/health

Examples

See the included example files:

  • templates/blog-post.html - Blog post template
  • templates/page.html - General page template
  • content/docs/en_getting-started.tpl.toml - Getting started page
  • content/docs/es_getting-started.tpl.toml - Spanish getting started page
  • content/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_name to 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.