Getting Started
To use Hauchiwa, you don't install a CLI tool. Instead, you create a new Rust binary project that acts as your site generator.
Installation
First, create a new Rust project:
cargo new generator
cd generator
Then, add Hauchiwa, Serde, and a Markdown renderer to your Cargo.toml:
[dependencies]
hauchiwa = "0.22.1"
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
comrak = "0.50"
Quick start
This minimal example sets up a pipeline that reads Markdown files and converts them into HTML files.
Open src/main.rs and paste the following:
use hauchiwa::{Blueprint, Output};
use serde::Deserialize;
// 1. Define your Frontmatter
// This matches the YAML at the top of your markdown files.
#[derive(Clone, Deserialize, Debug)]
struct Frontmatter {
title: String,
}
fn main() -> anyhow::Result<()> {
// 2. Create the Blueprint
let mut config = Blueprint::<()>::new();
// 3. Register a Loader (Input)
// This scans for .md files in the "content" directory.
// 'pages' is a Handle representing all future markdown files.
let pages = config.load_documents::<Frontmatter>()
.glob("content/**/*.md")?
.base("content")
.register();
// 4. Define a Task (Processing)
// We use .each().map() to process files one by one.
// During watch rebuilds, unchanged documents can reuse their rendered output.
config.task()
.each(pages)
.map(|_ctx, doc, ()| {
// Hauchiwa parses frontmatter; Comrak renders the Markdown body.
let html = comrak::markdown_to_html(&doc.text, &comrak::Options::default());
// 5. Write the page at its public route, derived from .base("content").
Ok(Output::to(doc).html(html)?)
});
// 6. Run the Website
config.finish().build(())?;
Ok(())
}
Running it
Create a dummy content file to test it:
mkdir content
printf -- '---\ntitle: Hello Hauchiwa\n---\n# Content\n' > content/index.md
Now run your generator:
cargo run
Check the newly created dist/ directory (the default output location). You will see dist/index.html.
You should see:
<h1>Content</h1>
The YAML title is available as doc.matter.title for your page template. The
body is available as doc.text; the document loader does not render Markdown.
With .base("content"), content/index.md maps to /, and
content/about.md maps to /about/ (dist/about/index.html). Without .base(),
the source directory remains part of the route. doc.meta.path always retains
the original source path, while doc.meta.href holds the public route.
Continue with Building out your site to add a shared template, navigation, CSS, and a live development preview.