Expand description
§Hauchiwa
A flexible, incremental, graph-based static site generator library for Rust. It provides the building blocks to create your own custom static site generator tailored exactly to your needs.
Create tasks and orchestrate them using simple primitives, which are type-checked by the Rust compiler. Each task can do a different thing, such as load images, bundle JS, parse markdown, render Jinja templates. This library already has some built-in tasks, but you can always define custom tasks when needed.
The overarching goal is to create an easy-to-use tool with near instantaneous rebuilds, which will work forever and be immune to churn by embracing web standards. The moment you start using this library you won’t ever need to move to anything else.
§Quick Start
Add hauchiwa to your Cargo.toml:
[dependencies]
# Check crates.io for the latest version
hauchiwa = "*"
# Serde is needed to parse frontmatter
serde = { version = "1", features = ["derive"] }Create your generator in src/main.rs:
use hauchiwa::{Blueprint, Output};
use serde::Deserialize;
// 1. Define your content structure (Frontmatter)
#[derive(Deserialize, Clone)]
struct Post {
title: String,
}
fn main() -> anyhow::Result<()> {
// 2. Create the configuration
// We explicitly specify the global data type as `()`
// since we don't have any global state yet.
let mut config = Blueprint::<()>::new();
// 3. Add a loader to glob markdown files
// `posts` is `Many<Document<Post>>`
let posts = config.load_documents::<Post>()
.source("content/**/*.md")
.register()?;
let css = config.load_css()
.entry("styles/**/*.scss")
.register()?;
// 4. Define a task to render pages
// We declare that this task depends on `posts`.
config
.task()
.each(posts)
.using(css)
// Iterate over loaded posts
.map(|_, post, css| {
// retrieve css bundle path
let css = css.get("styles/main.scss")?;
// format html
let html_content = format!(
"<link rel=\"stylesheet\" href=\"/{}\"><h1>{}</h1>",
css.path, post.matter.title
);
// Output::html creates pretty URLs (e.g., /foo/index.html)
Ok(Output::html(&post.meta.path, html_content))
});
// 5. Build the website
let mut website = config.finish();
website.build(())?;
Ok(())
}§Key features
- Parallel: Define your build as a graph where tasks are wired together using strictly typed handles, ensuring ideal parallelism.
- Incremental: By re-executing only chains of dirty tasks, we can avoid unneeded rebuilds and deliver near-instant updates.
- Type-safe: Dependencies are passed as generic tokens, allowing the Rust compiler to enforce that the output type perfectly matches the input type.
- Content-addressed: Assets are stored by their hash, guaranteeing cache-busting, deduplication, and reliable incremental builds out-of-the-box.
§Built-in support for
- Static files: Copy arbitrary file trees into
dist/. - Content: Parse Markdown and Frontmatter safely into strongly-typed Rust structs.
- Templating: Render pages using
minijinja(Jinja2 syntax) templates. - CSS/Sass: Integrate
grassto compile and minify stylesheets. - Images: Generate optimized multi-format images via the
imagecrate. - JavaScript: Bundle and minify JS/TS via
esbuild. - Svelte: Compile components into separate SSR and hydration scripts.
- Search: Static search indexing via
pagefind. - Sitemap: Sitemap generation via
sitemap-rs.
Need something else?
Hauchiwa is designed to be extensible. You can write custom tasks in standard Rust to handle anything not included out-of-the-box. The engine automatically applies the exact same caching, parallelism, and compile-time type safety to custom tasks.
§Documentation
Introduction is available in the docs/ directory (run make watch), or you
can visit the online version. The best place to
learn the API is the full documentation. It covers
the available features in depth.
§Examples
Some examples are available in the examples/ directory.
In addition, there are also some real-world examples:
§Feature flags
Default features (opt out if not needed):
grass: Enables SCSS/Sass compilation.image: Enables image optimization (WebP, resizing).tokio: Enables the Tokio runtime for async tasks.live: Enables live-reload during development.server: Enables the built-in development server.
Opt-in features:
pagefind: Enables static search indexing.sitemap: Enablessitemap.xmlgeneration.minijinja: Enables Jinja2-style template loading.logging: Enablesinit_logging(), which sets up atracingsubscriber with ANSI colours, uptime timestamps, and progress bar integration.
§License
GPL-2.0 or later.
Re-exports§
Modules§
- error
- loader
- Loaders are tasks that ingest data from the filesystem or external sources.
- output
- Utilities for working with output data and paths.
- prelude
- tracing
Structs§
- Blueprint
- The blueprint for your static site.
- Diagnostics
- Build diagnostics and performance metrics.
- Environment
- Global configuration and state available to all tasks.
- File
Metadata - Metadata about a file in the project structure.
- Import
Map - This matches the browser’s Import Map specification. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap
- Many
- A “fine” type-safe reference to a task in the build graph.
- One
- A “coarse” type-safe reference to a task in the build graph.
- Store
- A helper for managing side effects and imports within a task.
- Task
Context - The context passed to every task execution.
- Tracker
- A collection of assets tracked with fine-grained granularity.
- Website
- Represents the configured site and provides methods for building and serving it with a development server.
Enums§
- Mode
- The mode in which the site generator is running.