Skip to main content

Command Palette

Search for a command to run...

How to use Tera templates with Axum(Rust)

Updated
2 min read

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.