My MiniJinja Starter Template
January 2024
Ready To Copy/Paste
This is the basic MiniJinja1 code I use to get started with a new project:
Check out the rust_gimiore for a refined version of this that will eventually take this place.
Old Notes
This is my basic starer as of June, 2025.
---
[dependencies]
anyhow = "1.0.98"
minijinja = { version = "2.9.0", features = ["custom_syntax", "loader"] }
serde = {version = "1.0.219", features = ["derive"] }
---
use anyhow::Result;
use minijinja::{Environment, Value, context};
use minijinja::syntax::SyntaxConfig;
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize)]
struct Payload {
name: String
}
fn main() -> Result<()> {
let payload = Payload{ name: "MiniJinja".to_string() };
output_content(&payload)?;
println!("Done");
Ok(())
}
fn output_content(payload: &Payload) -> Result<()> {
let mut env = get_env();
env.add_template_owned(
"template", template_content()
)?;
let jinja = env.get_template("template")?;
let data = Value::from_serialize(payload);
let output = jinja.render(context!(data => data))?;
println!("{}", output);
Ok(())
}
fn get_env() -> Environment<'static> {
let mut env = Environment::new();
env.set_syntax(
SyntaxConfig::builder()
.block_delimiters("[!", "!]")
.variable_delimiters("[@", "@]")
.comment_delimiters("[#", "#]")
.build()
.unwrap(),
);
env
}
fn template_content() -> String {
r#"<!DOCTYPE html>
<html lang="en">
<head>
<meta<meta charset="UTF-8">
</head>
<body>
<h1>
Hello, [@ data.name @]!
</h1>
</body>
</html>"#.to_string()
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta<meta charset="UTF-8">
</head>
<body>
<h1>
Hello, MiniJinja!
</h1>
</body>
</html>
Done
---
[dependencies]
minijinja = { version = "2.9.0", features = ["custom_syntax", "loader"] }
---
use minijinja::{Environment, Value, context};
use minijinja::syntax::SyntaxConfig;
fn main() {
let name = Value::from("MiniJinja");
let mut env = get_env();
env.add_template_owned(
"example-template", make_template()
).unwrap();
match env.get_template("example-template") {
Ok(jinja) => {
match jinja.render(
context!(name)
) {
Ok(output) => {
println!("{}", output);
}
Err(e) => {
println!("{}", e);
}
}
}
Err(e) => {
println!("{}", e);
}
}
}
fn get_env() -> Environment<'static> {
let mut env = Environment::new();
env.set_syntax(
SyntaxConfig::builder()
.block_delimiters("[!", "!]")
.variable_delimiters("[@", "@]")
.comment_delimiters("[#", "#]")
.build()
.unwrap(),
);
env
}
fn make_template() -> String {
r#"<!DOCTYPE html>
<html lang="en">
<head>
<meta<meta charset="UTF-8">
</head>
<body>
<h1>
Hello, [@ name @]!
</h1>
</body>
</html>"#.to_string()
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta<meta charset="UTF-8">
</head>
<body>
<h1>
Hello, MiniJinja!
</h1>
</body>
</html>
Custom Tokens vs. Default Tokens
I use custom tokens for my MiniJinja projects. They are changed using the .set_syntax() call in the get_env() function. Specifically:
-
{% %} becomes [! !]
-
{{ }} becomes [@ @]
-
{# #} becomes [# #]
If find the square brackets easier to track visually. I also find hitting Shift+1 easier than hitting Shift+5.
You can switch to the default tokes by replacing:
in the main() function with:
let mut env = Environment::new();
and then deleting the get_env() function.
My Go-To Engine
I use MiniJinja for Neopoligen2. My site is currently 2,963 pages. It outputs in less than 10 seconds with an empty cache3. I could probably add some optimizations, but it's plenty fast for me as is. I've yet to run into something that I can't get it to do.
Definitely worth checking out if you're in the market.
-a