The theme system for Blogr static site generator, providing beautiful and customizable themes for blogs.
Blogr Themes is a library that provides the theme system for the Blogr static site generator. It includes built-in themes and a flexible architecture for creating custom themes.
Current Version: 0.4.1
This crate uses independent versioning from the main Blogr CLI to allow for theme-specific updates and improvements.
- Multiple built-in themes - Ready-to-use professional themes
- Flexible theme system - Easy to extend and customize
- Responsive designs - Mobile-first responsive layouts
- Dark/light mode support - Automatic and manual theme switching
- TUI integration - Terminal UI support for theme preview
- Asset bundling - Embedded CSS, templates, and assets
- Performance optimized - Minimal CSS and fast rendering
- Version: 1.0.0
- Style: Clean, artistic design with retro typography
- Features: Warm color palette, serif fonts, minimalist layout
- Best for: Personal blogs, creative writing, photography
- Version: 1.0.0
- Style: Modern dark theme inspired by Obsidian
- Features: Dark/light mode, purple accents, clean typography
- Best for: Technical blogs, documentation, note-taking style content
- Version: 1.0.0
- Style: Quirky terminal-inspired design with pastel colors
- Features: Glitch effects, ASCII art, typewriter animations
- Best for: Creative personal blogs, tech enthusiasts
- Version: 1.0.0
- Style: Minimal brutalist design with pops of color
- Features: Bold typography, high contrast, clean layout
- Best for: Minimalist blogs, design-forward content
- Version: 1.0.0
- Style: Dark minimalist theme with neon accents
- Features: Cyberpunk aesthetic, animated backgrounds, customizable status bar
- Best for: Personal portfolios, designer/developer showcases
- Version: 1.0.0
- Style: Dynamic content-loading theme with modern aesthetics
- Features: Smooth animations, clean typography, responsive design
- Best for: Personal websites, project showcases
- Version: 1.0.0
- Style: Modern glassmorphic portfolio theme
- Features: Frosted glass effects, elegant transitions, professional layout
- Best for: Professional portfolios, freelancers
- Version: 1.0.0
- Style: Vintage typewriter-inspired theme with nostalgic aesthetics
- Features:
- Vintage cream paper background with subtle texture
- Monospace Courier font family
- Typewriter typing animation for title
- Blinking cursor effect
- Vintage date stamp
- Typewriter-style line separators
- Configurable paper texture, animations, and cursor
- Best for: Writers, bloggers, literary portfolios, creative professionals
Add to your Cargo.toml:
[dependencies]
blogr-themes = "0.4.1"use blogr_themes::{ThemeManager, get_theme};
// Get a theme by name
let theme = get_theme("minimal_retro")?;
// Get theme information
let info = theme.info();
println!("Theme: {} v{}", info.name, info.version);
// Get templates
let templates = theme.templates();
let base_template = templates.get("base.html").unwrap();
// Get assets (CSS, images, etc.)
let assets = theme.assets();use blogr_themes::ThemeManager;
let mut manager = ThemeManager::new();
// List available themes
let themes = manager.list_themes();
for theme_name in themes {
println!("Available theme: {}", theme_name);
}
// Load a specific theme
let theme = manager.load_theme("obsidian")?;Each theme implements the Theme trait:
pub trait Theme: Send + Sync {
fn info(&self) -> ThemeInfo;
fn templates(&self) -> ThemeTemplates;
fn assets(&self) -> HashMap<String, Vec<u8>>;
fn preview_tui_style(&self) -> ratatui::style::Style;
}Templates are built using a builder pattern:
pub struct ThemeTemplates {
templates: Vec<(&'static str, &'static str)>,
}
impl ThemeTemplates {
pub fn new(base_template_name: &'static str, base_template: &'static str) -> Self;
pub fn with_template(self, name: &'static str, template: &'static str) -> Self;
}pub struct ThemeInfo {
pub name: String,
pub version: String,
pub author: String,
pub description: String,
pub config_schema: HashMap<String, ConfigOption>,
pub site_type: SiteType, // Blog or Personal
}Themes can define configurable options:
pub struct ConfigOption {
pub value: toml::Value, // Configuration value (string, bool, integer, float, etc.)
pub description: String, // Help text
}Themes use the Tera templating engine with these standard templates:
base.html- Base layout templateindex.html- Homepage templatepost.html- Individual post templatearchive.html- Archive page templatetags.html- Tags index templatetag.html- Individual tag page template
Common variables available in templates:
<!-- Site configuration -->
{{ site.blog.title }}
{{ site.blog.description }}
{{ site.blog.author }}
{{ site.theme.config.* }}
<!-- Post data -->
{{ post.metadata.title }}
{{ post.metadata.date }}
{{ post.metadata.tags }}
{{ post.content }}
<!-- Collections -->
{{ posts }} <!-- All posts -->
{{ tags }} <!-- All tags with counts -->Built-in template functions:
<!-- Generate URLs -->
{{ url(path="posts/my-post.html") }}
{{ asset_url(path="css/style.css") }}
<!-- Date formatting -->
{{ post.metadata.date | date(format="%Y-%m-%d") }}use blogr_themes::{Theme, ThemeInfo, ThemeTemplates, ConfigOption, SiteType};
use std::collections::HashMap;
pub struct MyCustomTheme;
impl Theme for MyCustomTheme {
fn info(&self) -> ThemeInfo {
let mut schema = HashMap::new();
schema.insert("primary_color".to_string(), ConfigOption {
value: toml::Value::String("#007acc".to_string()),
description: "Primary theme color".to_string(),
});
ThemeInfo {
name: "My Custom Theme".to_string(),
version: "1.0.0".to_string(),
author: "Your Name".to_string(),
description: "A custom theme for my blog".to_string(),
config_schema: schema,
site_type: SiteType::Blog,
}
}
fn templates(&self) -> ThemeTemplates {
ThemeTemplates::new("base.html", include_str!("templates/base.html"))
.with_template("index.html", include_str!("templates/index.html"))
.with_template("post.html", include_str!("templates/post.html"))
.with_template("archive.html", include_str!("templates/archive.html"))
.with_template("tags.html", include_str!("templates/tags.html"))
.with_template("tag.html", include_str!("templates/tag.html"))
}
fn assets(&self) -> HashMap<String, Vec<u8>> {
let mut assets = HashMap::new();
assets.insert(
"css/style.css".to_string(),
include_bytes!("assets/style.css").to_vec(),
);
// Add more assets...
assets
}
fn preview_tui_style(&self) -> ratatui::style::Style {
use ratatui::style::{Color, Style};
Style::default()
.fg(Color::Blue)
.bg(Color::Black)
}
}use blogr_themes::ThemeManager;
let mut manager = ThemeManager::new();
manager.register_theme("my_custom", Box::new(MyCustomTheme));Themes can bundle assets (CSS, images, fonts) directly into the binary:
fn assets(&self) -> HashMap<String, Vec<u8>> {
let mut assets = HashMap::new();
// Bundle CSS
assets.insert(
"css/style.css".to_string(),
include_bytes!("assets/style.css").to_vec(),
);
// Bundle images
assets.insert(
"images/logo.png".to_string(),
include_bytes!("assets/logo.png").to_vec(),
);
assets
}Themes can provide custom styling for the terminal user interface:
fn preview_tui_style(&self) -> ratatui::style::Style {
use ratatui::style::{Color, Style};
Style::default()
.fg(Color::Rgb(167, 139, 250)) // Purple accent
.bg(Color::Rgb(32, 32, 32)) // Dark background
}cargo buildcargo test- Create a new module in
src/ - Implement the
Themetrait - Add templates in
templates/ - Add assets in
assets/ - Register the theme in
lib.rs - Update the theme manager
We welcome theme contributions! Please:
- Follow the existing theme structure
- Ensure responsive design
- Test across different content types
- Document configuration options
- Include preview screenshots
See the main CONTRIBUTING.md for detailed guidelines.
- NEW: External post support — posts can link to external URLs
- IMPROVED: Search indexing with better plain text extraction
- NEW: Newsletter API endpoints for creating and sending newsletters
- IMPROVED: Newsletter hardening with cleanup, rate limiting, and validation
- NEW: Typewriter theme for personal websites with vintage aesthetics
- NEW: Brutja theme — minimal brutalist blog theme with pops of color
- NEW: Blog link support in all personal website themes (Dark Minimal, Musashi, Slate Portfolio, Typewriter)
- IMPROVED: Personal mode now uses title and description from content.md instead of blogr.toml
- IMPROVED: Conditional separator lines in Typewriter theme based on section presence
- ADDED: Vintage typewriter effects including typing animation, blinking cursor, and paper texture
- NEW: Personal website themes (Dark Minimal, Musashi, Slate Portfolio)
- NEW: Terminal Candy theme for blogs
- IMPROVED: Better theme organization for blog vs personal modes
- ADDED: Personal mode support with section-based layouts
- NEW: Obsidian theme improvements
- IMPROVED: Better responsive design across all themes
- FIXED: Content centering and layout issues
- ADDED: Enhanced CSS bundling system
- Initial release with minimal_retro and obsidian themes
- Basic theme system architecture
- TUI integration support
This project is licensed under the MIT License - see the LICENSE file for details.
- Documentation: Full documentation
- Issues: GitHub Issues
- Theme Requests: GitHub Discussions
Made with ❤️ by bahdotsh