rs-web - Static Site Generator
A fast, opinionated static site generator built in Rust with support for:
- Markdown processing with syntax highlighting, external link handling
- Content encryption (full post or partial
:::encryptedblocks) - HTML content files with Tera templating support
- Link graph with backlinks and visualization (Obsidian-style)
- RSS feed generation with section filtering
- Parallel processing for fast builds
Installation
Or with Nix:
Quick Start
# Build the site
# Build to custom output directory
# Watch for changes and rebuild incrementally
Logging
Control log verbosity with --debug, --log-level, or the RS_WEB_LOG_LEVEL environment variable.
# Enable debug logging (shorthand)
# Set specific log level (trace, debug, info, warning, error)
# Use environment variable
RS_WEB_LOG_LEVEL=debug
Priority order: --debug > --log-level > RS_WEB_LOG_LEVEL > default (warning)
Configuration
Configure via config.toml:
Required Settings
[]
= "My Site" # Site title
= "Site description" # Site description
= "https://example.com" # Base URL (no trailing slash)
= "Your Name" # Author name
[]
= "@username" # Optional: Twitter handle
= "/static/og.png" # Optional: Default OG image
[]
= "dist" # Output directory
= true # Default: true
[]
= 85.0 # WebP quality (default: 85.0)
= 1.0 # Image scale (default: 1.0)
Optional Settings (have defaults)
[]
= "content" # Content directory (default: "content")
= "styles" # Styles directory (default: "styles")
= "static" # Static files (default: "static")
= "templates" # Templates (default: "templates")
= "index.md" # Home page file (default: "index.md")
= ["drafts", "^temp.*"] # Regex patterns to exclude files/dirs (default: [])
= true # Exclude README.md, LICENSE.md, etc. (default: true)
= true # Respect .gitignore (default: true)
[]
= ["John Doe", "Jane Doe"] # Names to highlight (default: [])
= "me" # CSS class for highlights (default: "me")
[]
= "post.html" # Section -> template mapping
= "project.html" # (default: uses {section}.html or post.html)
[]
= "/:year/:month/:slug/" # Section -> URL pattern
= "/:slug/" # Placeholders: :year :month :day :slug :title :section
[]
= "pass show site" # Command to get password (optional)
= "secret" # Raw password (optional, less secure)
# Priority: SITE_PASSWORD env > command > password
[]
= true # Enable graph generation (default: true)
= "graph.html" # Graph page template (default: "graph.html")
= "graph" # URL path (default: "graph" -> /graph/)
[]
= true # Enable RSS generation (default: true)
= "rss.xml" # Output filename (default: "rss.xml")
= ["blog"] # Sections to include (default: [] = all)
= 20 # Max items (default: 20)
= false # Exclude posts with :::encrypted (default: false)
Root Pages
Markdown files at the content root (besides the home page) are processed as standalone pages. For example, 404.md becomes 404.html:
---
title: "404 - Page Not Found"
template: "error.html"
---
# Page Not Found
The page you're looking for doesn't exist.
Default excluded files (disable with exclude_defaults = false):
- README.md, LICENSE.md, CHANGELOG.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md
- Hidden files (starting with
.)
Frontmatter
Post frontmatter options (YAML or TOML):
---
title: "Post Title" # Required
description: "Description" # Optional
date: # Optional (YAML date or string)
tags: # Optional
draft: false # Optional (default: false, excluded from build)
image: "/static/post.png" # Optional: OG image
template: "custom.html" # Optional: Override template
slug: "custom-slug" # Optional: Override URL slug
permalink: "/custom/url/" # Optional: Full URL override
encrypted: false # Optional: Encrypt entire post
password: "post-secret" # Optional: Post-specific password
---
Content Types
Markdown Files (.md)
Standard markdown files processed through the markdown pipeline.
HTML Files (.html)
HTML files with Tera templating support. Can use extends, includes, and all Tera features:
+++
title = "Custom Page"
date = 2024-01-15
+++
{% extends "base.html" %}
{% block content %}
{{ post.title }}
By {{ site.author }}
{% endblock %}
Partial Encryption
Markdown
Use :::encrypted blocks for partial content encryption:
Public content here.
:::encrypted
This content is encrypted with the global/post password.
:::
:::encrypted password="custom"
This block has its own password.
:::
HTML
Use <encrypted> tags in HTML files:
Public content here.
This content is encrypted.
This block has its own password.
Template Variables
Home Template (home.html)
site- Site config (title, description, base_url, author)page- Page info (title, description, url, image)sections- All sections with posts (sections.blog.posts)content- Rendered markdown content
Post Template (post.html)
site- Site configpost- Post info (title, url, date, tags, reading_time, etc.)page- Page info for head.html compatibilitycontent- Rendered markdown contentbacklinks- Posts linking to this post (url, title, section)graph- Local graph data (nodes, edges) for visualization
Graph Template (graph.html)
site- Site configpage- Page infograph- Full graph data (nodes, edges)
License
MIT License. See LICENSE for details.