DOCUMENTATION / CORE FRAMEWORK

Rendering template files

See CSS, JavaScript, Chart.js, Lucide, Bootstrap and static assets.

In this lesson, a page uses a separate HTML template rather than embedding its markup inside a route. The application then serves CSS and JavaScript from a public static directory.

View the frontend example to see the template output and the actual CSS/JavaScript assets.

1. Create a small project

mojara new dashboard web
cd dashboard

Create this application structure:

dashboard/
  app.mojo
  templates/
    dashboard.html
  static/
    css/
      site.css
    js/
      app.js

2. Write the template file

Create templates/dashboard.html:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{{ page_title }}</title>
  <link rel="stylesheet" href="/static/css/site.css">
  <script defer src="/static/js/app.js"></script>
</head>
<body>
  <header><strong>Mojara Dashboard</strong></header>
  <main>
    <h1>Welcome, {{ name }}!</h1>
    <p>This page was rendered from a template file.</p>
    <button id="greet" type="button">Say hello</button>
    <p id="message" role="status"></p>
  </main>
</body>
</html>

{{ page_title }} and {{ name }} mark values supplied when the template is rendered. The link and script elements load static files.

3. Render the template from a route

from mojara import App, Request, Response, render_template

def dashboard(req: Request) -> Response:
    var html = render_template(
        "dashboard.html",
        {"page_title": "My Dashboard", "name": "Amina"},
    )
    return Response.html(html)

def main() raises:
    var app = App()
    app.get("/", dashboard)
    app.static("/static", directory="static")
    app.run(port=8000)

The handler renders dashboard.html using the supplied values. The static mapping makes static/css/site.css available at /static/css/site.css, and likewise for the JavaScript.

Render user data with HTML escaping enabled. Keep private source, configuration, and template files outside the static directory.

4. Add your CSS

Create static/css/site.css:

:root { font-family: system-ui, sans-serif; color: #321a0d; }
body { margin: 0; background: #fff9ee; }
header { padding: 16px 24px; background: #f27818; color: white; }
main { max-width: 720px; margin: 48px auto; padding: 24px; }
h1 { color: #b94a0d; }
button { background: #e8691e; color: white; border: 0; padding: 12px 18px; cursor: pointer; }
button:hover { background: #c34f13; }

This stylesheet controls the background, header, typography, layout and button style without changing the Mojo route.

5. Add JavaScript

Create static/js/app.js:

document.querySelector("#greet").addEventListener("click", () => {
  document.querySelector("#message").textContent = "Hello from JavaScript!";
});

The defer attribute causes the script to execute after the HTML is parsed. Clicking Say hello updates the page without reloading.

6. Run and inspect

mojara dev

Open the address printed by Mojara, then check the static resources:

curl -i http://127.0.0.1:8000/
curl -i http://127.0.0.1:8000/static/css/site.css
curl -i http://127.0.0.1:8000/static/js/app.js

The first request returns HTML; the second and third return CSS and JavaScript. If your server uses another port, substitute that port.

Next: Adding JavaScript and CSS libraries.