- 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>
361 lines
9.3 KiB
Markdown
361 lines
9.3 KiB
Markdown
# 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:
|
|
|
|
```html
|
|
<!-- 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:
|
|
|
|
```toml
|
|
# 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`:
|
|
|
|
```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`:
|
|
|
|
```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`:
|
|
|
|
```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
|
|
|
|
```toml
|
|
# 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:
|
|
```html
|
|
{{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
|
|
|
|
```rust
|
|
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
|
|
|
|
```rust
|
|
// 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
|
|
|
|
```rust
|
|
// Add custom function to template service
|
|
template_service.add_function("current_year", |_: &HashMap<String, Value>| {
|
|
Ok(Value::Number(2024.into()))
|
|
})?;
|
|
```
|
|
|
|
### Template Inheritance
|
|
|
|
```html
|
|
<!-- templates/base.html -->
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>{% block title %}Default Title{% endblock %}</title>
|
|
</head>
|
|
<body>
|
|
{% block content %}{% endblock %}
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
```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. |