Primer template en Rust con Tera

Resumen

Configurar Tera en un proyecto Rust te permite separar la lógica de tu backend del HTML que renderiza el navegador, algo clave si quieres construir aplicaciones web mantenibles con Actix. Aquí aprendes a importar la dependencia, definir la ruta de tus templates y conectar todo dentro de un endpoint.

¿Cómo se importa Tera en un proyecto de Rust?

El primer paso es declarar la dependencia en Cargo.toml. En este caso usamos la versión 1.10.0 de Tera, que se referencia desde main.rs con use tera.

Una vez importada, Tera se registra como un data dentro de la función main para que esté disponible en toda la aplicación. La instancia se crea así:

rust let tera = Tera::new( concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*") ).unwrap();

La macro concat! une dos strings: la ruta absoluta del proyecto que entrega CARGO_MANIFEST_DIR y la subcarpeta templates. Los dos asteriscos **/* indican que Tera debe leer de forma recursiva todos los archivos dentro de esa carpeta.

¿Qué hace CARGO_MANIFEST_DIR en Rust? Es una variable de entorno que devuelve la ruta absoluta donde vive tu Cargo.toml. Sirve para que Tera encuentre los templates sin importar dónde se ejecute el binario.

¿Dónde debe ubicarse la carpeta templates?

La carpeta templates tiene que estar al mismo nivel que src, no dentro de ella. Este detalle es fácil de pasar por alto y suele ser la causa de errores al renderizar.

Dentro de templates colocas tus archivos HTML, por ejemplo un index.html con contenido tan simple como una etiqueta que diga "Mi primer template con Tera". Ese archivo es el que tu función en Rust va a leer y entregar al navegador.

¿Cómo conectar Tera a un endpoint en Actix?

Para servir el template desde una ruta, defines una función asíncrona que devuelva un impl Responder. La instancia de Tera se inyecta como argumento usando los extractores de Actix:

rust #[get("/prueba-tera")] async fn tera_test(template_manager: web::Data<Tera>) -> impl Responder { let mut ctx = tera::Context::new(); HttpResponse::Ok() .content_type("text/html") .body(template_manager.render("index.html", &ctx).unwrap()) }

Fíjate en tres detalles. El content_type debe ser text/html para que el navegador interprete la respuesta como página web. El método render recibe el nombre del archivo y un contexto. Y el unwrap cierra la operación, porque renderizar puede fallar si el template no existe o está corrupto.

¿Para qué sirve el contexto en Tera?

El contexto es la estructura donde guardas las variables que vas a inyectar en tu HTML. Aunque en este primer ejemplo no pasamos datos dinámicos, Tera exige un contexto como segundo parámetro de render.

Por eso se declara let mut ctx = tera::Context::new();. Se marca como mut porque normalmente vas a ir agregando valores con ctx.insert(...) antes de renderizar.

¿Qué es el contexto en Tera? Es un contenedor de variables que viaja desde tu código Rust hasta el HTML. Si quieres mostrar el nombre de un usuario o una lista de posts, los insertas ahí.

¿Qué errores aparecen al configurar Tera por primera vez?

Durante la configuración suelen aparecer tres tropiezos comunes que vale la pena anticipar:

  • Nombrar la variable como tera cuando ya existe un módulo tera en el scope. La solución es renombrarla, por ejemplo a tera_test.
  • Olvidar registrar la función con .service(tera_test) dentro del App, lo que hace que la URL devuelva un 404.
  • Confundir el nombre de la función con la ruta. La función puede llamarse tera_test, pero la URL definida en el #[get] es /prueba-tera.

También es fácil dejar un punto y coma de más al final de la expresión que se devuelve, lo cual rompe el retorno implícito de Rust. Quitarlo o usar return explícito resuelve el problema.

¿Cómo verificar que Tera está renderizando bien?

Después de ajustar los detalles, ejecutas cargo run. La primera compilación tarda más porque descarga todas las dependencias, pero las siguientes son rápidas.

Al entrar al navegador en la ruta /prueba-tera, deberías ver el texto "Mi primer template con Tera". Si aparece, significa que la cadena completa funciona: Actix recibe la petición, Tera localiza el archivo en templates, lo renderiza con el contexto y lo devuelve con el content_type correcto.

Con esto ya tienes una base sólida para empezar a inyectar datos dinámicos. Modifica el HTML, agrega una imagen y cuéntame en los comentarios qué decidiste mostrar en tu primer template.