How to use Tera templates with Axum(Rust)
Initialize the project
Create a new Rust project and initialize it.
mkdir axum-tera
cd axum-tera
cargo init
Edit your Cargo.toml file:
[package]
name = "axum-tera"
version = "0.1.0"
edition = "2024"
[dependencies]
axum = "0.8.4"
tokio = { version = "1", features = ["full"] }
tera = "1"
How to implement tera in your axum rust code (main.rs):
use std::sync::Arc;
use tera::{Tera, Context};
use axum::{extract::State, routing::get, Router, response::Html};
#[derive(Clone)]
struct AppState {
tera: Tera,
}
#[tokio::main]
async fn main() {
// templates/**/*.html tells Tera to load all .html files inside the templates
// folder and its subfolders.
let tera = match Tera::new("templates/**/*.html") {
Ok(t) => t,
Err(e) => {
println!("Parsing error(s): {}", e);
::std::process::exit(1);
}
};
let file_state = Arc::new(AppState{
tera,
});
let app = Router::new()
.route("/", get(hello_template))
.with_state(file_state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap();
println!("listening on {}", listener.local_addr().unwrap());
axum::serve(listener, app).await.unwrap();
}
async fn hello_template(State(state): State<Arc<AppState>>) -> Html<String> {
let mut context = Context::new();
context.insert("name", "Nishant");
let rendered = state.tera.render("index.html", &context)
.unwrap_or_else(|e| format!("Template error: {}", e));
Html(rendered)
}
Create a new file at templates/index.html or templates/index.html.tera :
<!DOCTYPE html>
<html>
<head>
<title>Hello Tera</title>
</head>
<body>
<h1>Hello, {{name}}! This is rendered with Tera.</h1>
</body>
</html>
Now, run your axum server:
cargo run
# or
cargo build
/target/debug/axum-tera
Visit http://localhost:8000/ to see your Tera template is rendered.
Expected output in the end is: Hello, Nishant! This is rendered with Tera.
That’s it — you now have Tera templates working with Axum. From here, you can extend this by adding routes, layouts, or dynamic data.