Fast, memory-safe, and extensible — built in Rust.
- Install — prerequisites, crate, library dependency
- Overview — what SSG does
- Architecture — build pipeline diagram
- Features — capability matrix
- The CLI — flags and usage
- First 5 Minutes — clone → tests passing
- Library Usage —
ssg::run(), plugins, incremental builds - Benchmarks — binary size, test suite, coverage
- Development — make targets, contributing
- What's Included — modules, security, tests
- License
| Platform | Setup |
|---|---|
| macOS | brew install rustup-init && rustup-init -y, or follow rustup.rs |
| Linux / WSL | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| Windows (native) | Download rustup-init.exe. Native build is supported; the make targets below require Git Bash or WSL |
SSG requires Rust 1.88.0 or later (pinned in rust-toolchain.toml). Verify with rustc --version.
cargo install ssgOr add as a library dependency:
[dependencies]
ssg = "0.0.35"SSG generates static websites from Markdown content, YAML frontmatter, and HTML templates. It compiles everything into production-ready HTML with built-in SEO metadata, accessibility compliance, and feed generation. The plugin system handles the rest.
- Zero-cost performance through Rust's ownership model and parallel file operations
- Incremental builds with content fingerprinting — only changed files are reprocessed
- File watching with automatic rebuild on content changes
- Plugin architecture with lifecycle hooks for custom processing
- WCAG 2.1 Level AA accessibility compliance in generated output
graph TD
A[Content: Markdown + YAML] --> B{SSG CLI}
B --> C[Incremental Cache]
C --> D[Compile: staticdatagen]
D --> E[Plugin Pipeline]
E --> F[Minify / Optimize / Deploy]
D --> G[Dev Server: http_handle]
B --> H[File Watcher]
H -->|changed files| C
| Performance | Parallel file operations with Rayon, iterative traversal with depth bounds, incremental builds |
| Content | Markdown, YAML frontmatter, JSON, TOML. Atom and RSS feed generation |
| SEO | Meta tags, Open Graph, sitemaps, structured data, canonical URLs |
| Accessibility | Automatic WCAG 2.1 Level AA compliance |
| Theming | Custom HTML templates with variable substitution |
| Plugins | Lifecycle hooks: before_compile, after_compile, on_serve. Built-in minify, image-opti, deploy |
| Watch mode | Polling-based file watcher with configurable interval |
| Caching | Content fingerprinting via .ssg-cache.json for fast rebuilds |
| Config | TOML config files with JSON Schema for IDE autocomplete (ssg.schema.json) |
| Security | #![forbid(unsafe_code)], path traversal prevention, symlink rejection, file size limits |
| CI | Shared rust-ci.yml pipeline on stable toolchain, plus cargo audit, cargo deny, dependency review and SBOM generation |
| Command | What it does |
|---|---|
ssg -n mysite -c content -o build -t templates |
Generate a site from source directories |
ssg --config config.toml |
Load configuration from a TOML file |
ssg --serve public |
Serve from a specific directory |
ssg --watch |
Watch content for changes and rebuild |
Full CLI reference
Usage: ssg [OPTIONS]
Options:
-f, --config <FILE> Configuration file path
-n, --new <NAME> Create new project
-c, --content <DIR> Content directory
-o, --output <DIR> Output directory
-t, --template <DIR> Template directory
-s, --serve <DIR> Development server directory
-w, --watch Watch for changes and rebuild
--drafts Include draft pages in the build
--deploy <TARGET> Generate deployment config (netlify, vercel, cloudflare, github)
-q, --quiet Suppress non-error output
--verbose Show detailed build information
-h, --help Print help
-V, --version Print version
When no flags are provided, sensible defaults are used (content/, public/, templates/).
# 1 — Install
cargo install ssg # macOS / Linux / Windows
# 2 — Scaffold + build a brand-new site
ssg -n mysite -c content -o build -t templates
# 3 — Or build from source and run the bundled examples
git clone https://github.com/sebastienrousseau/shokunin.git
cd shokunin
cargo build # ~2 min cold, < 10 s incremental
cargo test --lib # 741 tests, ~8 s on M-series Mac
cargo run --example basic # minimal site
cargo run --example quickstart # opinionated defaults
cargo run --example plugins # plugin pipeline walk-through
cargo run --example multilingual # 28 locales + localized searchOn WSL/Linux the same commands work verbatim. On native Windows, replace
maketargets with theircargoequivalents (see Development).
make init # detects platform, installs rustfmt + clippy + cargo-deny,
# wires up the signed-commit git hook, and runs cargo buildThe bundled dev server binds to 127.0.0.1:3000 (or :8000 for the CLI). On WSL2, that loopback is reachable from your Windows host as long as localhostForwarding is enabled (the default since the Microsoft Store version of WSL). If your browser can't reach the site, override the bind address with environment variables — no code changes needed:
SSG_HOST=0.0.0.0 SSG_PORT=8080 cargo run --example multilingualThe same vars work for ssg --serve. Use 0.0.0.0 for Codespaces, dev-containers, and any remote-dev setup where the listener needs to be reachable from outside its network namespace.
// The simplest path: delegate to ssg's own pipeline.
#[tokio::main]
async fn main() -> anyhow::Result<()> {
ssg::run().await
}If you only want the compile primitive (no plugin pipeline, no dev server), depend on staticdatagen directly:
use staticdatagen::compiler::service::compile;
use std::path::Path;
fn main() -> anyhow::Result<()> {
compile(
Path::new("build"),
Path::new("content"),
Path::new("public"),
Path::new("templates"),
)?;
Ok(())
}Plugin example
use ssg::plugin::{Plugin, PluginContext, PluginManager};
use anyhow::Result;
use std::path::Path;
#[derive(Debug)]
struct LogPlugin;
impl Plugin for LogPlugin {
fn name(&self) -> &str { "logger" }
fn after_compile(&self, ctx: &PluginContext) -> Result<()> {
println!("Site compiled to {:?}", ctx.site_dir);
Ok(())
}
}
fn main() -> Result<()> {
let mut pm = PluginManager::new();
pm.register(LogPlugin);
pm.register(ssg::plugins::MinifyPlugin);
let ctx = PluginContext::new(
Path::new("content"),
Path::new("build"),
Path::new("public"),
Path::new("templates"),
);
pm.run_after_compile(&ctx)?;
Ok(())
}Incremental build example
use ssg::cache::BuildCache;
use std::path::Path;
let cache_path = Path::new(".ssg-cache.json");
let content_dir = Path::new("content");
let mut cache = BuildCache::load(cache_path).unwrap();
let changed = cache.changed_files(content_dir).unwrap();
if changed.is_empty() {
println!("No changes detected, skipping build.");
} else {
println!("Rebuilding {} changed files", changed.len());
// ... run build ...
cache.update(content_dir).unwrap();
cache.save().unwrap();
}| Metric | Value |
|---|---|
| Release binary | ~23 MB (unstripped), ~5 MB stripped with LTO |
| Unsafe code | 0 blocks — #![forbid(unsafe_code)] enforced |
| Test suite | 741 lib + 33 doc + integration tests. Run make bench for Criterion site-generation benchmarks (10/50/100 pages) |
| Dependencies | 24 direct, audited via cargo audit and cargo deny check (run make deny to reproduce). All CI refs pinned to SHA. |
| Coverage | ~98 % line coverage, measured with cargo llvm-cov |
| Plugin pipeline | Rayon-parallelised: search, SEO, canonical, and JSON-LD injection all use par_iter |
make init # One-command bootstrap (rustfmt + clippy + cargo-deny + hooks + build)
make build # Build the project
make test # Run all tests
make bench # Run performance benchmarks (Criterion)
make lint # Lint with Clippy
make format # Format with rustfmt
make deny # Check licenses and advisories
make doc # Generate API docs and open in browser
make clean # Remove build artifacts and stray logs
make hooks # Install the signed-commit git hookSee CONTRIBUTING.md for setup, signed commits, and PR guidelines.
Core modules
- cmd — CLI argument parsing,
SsgConfig, input validation - process — Argument-driven site processing and directory creation
- lib — Orchestrator:
run()→ plugin pipeline → compile → serve - plugin —
Plugintrait withbefore_compile,after_compile,on_servehooks - plugins — Built-in
MinifyPlugin,ImageOptiPlugin,DeployPlugin - cache — Content fingerprinting for incremental builds
- watch — Polling-based file watcher for live rebuild
- schema — JSON Schema generator for configuration
- scaffold — Project scaffolding (
ssg --new) - frontmatter — Frontmatter extraction and
.meta.jsonsidecar support - tera_engine — Tera templating engine integration
- tera_plugin — Tera template rendering plugin
- seo —
SeoPlugin,JsonLdPlugin,CanonicalPlugin,RobotsPlugin - search — Client-side search index generation + localized
SearchLabels - accessibility — Automated WCAG checker and ARIA validation
- ai — AI-readiness content hooks (alt-text validation,
llms.txt) - deploy — Deployment adapters (Netlify, Vercel, Cloudflare, GitHub Pages)
- assets — Asset fingerprinting and SRI hash generation
- highlight — Syntax highlighting plugin for code blocks
- shortcodes — Shortcode expansion (youtube, gist, figure, admonitions)
- markdown_ext — GFM extensions (tables, strikethrough, task lists)
- image_plugin — Image optimization with WebP output and responsive
srcset - livereload — WebSocket live-reload injection
- pagination — Pagination plugin for listing pages
- taxonomy — Taxonomy generation (tags, categories)
- drafts — Draft content filtering plugin
- stream — High-performance streaming file processor
- walk — Shared bounded directory walkers
Security and compliance
#![forbid(unsafe_code)]across the entire codebase- Path traversal prevention with
..detection and symlink rejection - File size limits (10 MB per file) and directory depth bounds (128 levels)
cargo auditwith zero warnings — all advisories tracked in.cargo/audit.tomlcargo deny— license, advisory, ban, and source checks all pass- SBOM generated as a release artifact
- Signed commits enforced via SSH ED25519
Test coverage
- 741 lib tests plus integration + fault-injection suites
- ~98 % library line coverage measured with cargo-llvm-cov
- CI runs on the shared
rust-ci.ymlpipeline (stabletoolchain)
THE ARCHITECT ᛫ Sebastien Rousseau THE ENGINE ᛞ EUXIS ᛫ Enterprise Unified Execution Intelligence System
Please read our Code of Conduct before participating in the project.
Dual-licensed under Apache 2.0 or MIT, at your option.
See CHANGELOG.md for release history.