Use CSS, JavaScript and frontend libraries
Mojara serves HTML over HTTP. The browser handles CSS, JavaScript, icons and charting libraries just as it does for any other web application.
You can use your own files from static/, libraries from a CDN, or bundled frontend dependencies.
Open the live frontend example to see local CSS and JavaScript, Lucide icons, Chart.js and a browser preference cookie working together.
1. Load a local CSS file
In templates/dashboard.html, add:
<link rel="stylesheet" href="/static/css/site.css">
Create static/css/site.css:
body { margin: 0; font-family: Arial, sans-serif; background: #fff8ec; }
h1 { color: #c54b0a; }
.action { border: 0; background: #ed751c; color: white; padding: 12px 16px; }
The browser requests /static/css/site.css when it loads the HTML. CSS changes affect the appearance without changing any backend code.
2. Load your own JavaScript file
In the same template:
<button id="add" class="action">Add item</button>
<p id="result"></p>
<script defer src="/static/js/app.js"></script>
Create static/js/app.js:
document.getElementById("add").addEventListener("click", () => {
document.getElementById("result").textContent = "Item added";
});
When the button is clicked, the text changes to Item added. The script is served as a static asset, not generated by the request handler.
3. Add Lucide icons
Add the icon markup and Lucide's UMD script:
<button class="action"><i data-lucide="plus"></i> Add item</button>
<script src="https://unpkg.com/lucide@0.468.0/dist/umd/lucide.min.js"></script>
<script>lucide.createIcons();</script>
The library replaces the placeholder with an SVG icon. You can use names such as search, home, settings, and check-circle. Load the library before calling lucide.createIcons().
4. Display a chart with Chart.js
Add a canvas to your template and load Chart.js:
<h2>Weekly activity</h2>
<canvas id="activity-chart" width="600" height="260"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
<script>
new Chart(document.getElementById("activity-chart"), {
type: "bar",
data: {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
datasets: [{
label: "Visits",
data: [12, 19, 10, 26, 17],
backgroundColor: "#ec781a"
}]
},
options: { responsive: true, scales: { y: { beginAtZero: true } } }
});
</script>
The browser renders a bar chart with five values. The data array can later come from a JSON endpoint in your Mojara app.
5. Call a Mojara API from JavaScript
If you have a route registered at /api/health:
async function loadHealth() {
const response = await fetch("/api/health");
if (!response.ok) throw new Error("Request failed");
const data = await response.json();
document.getElementById("status").textContent = data.status;
}
loadHealth().catch(console.error);
Add <span id="status">Loading...</span> to the template. The browser makes a GET request and updates the page using the JSON response.
6. Use a CSS framework such as Bootstrap
Include a pinned Bootstrap stylesheet:
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
>
Use its grid and form classes:
<div class="container py-4">
<div class="row g-3">
<div class="col-md-6">
<label for="name" class="form-label">Name</label>
<input id="name" class="form-control" placeholder="Your name">
</div>
<div class="col-md-6 d-flex align-items-end">
<button class="btn btn-warning">Save</button>
</div>
</div>
</div>
The layout displays two columns on wider screens and stacks them on narrow screens. Bootstrap is a frontend library: Mojara does not need a special adapter for its CSS.
7. Keep libraries on your own server
If you prefer not to load files from external CDNs, save your third-party assets in:
static/
vendor/
chart.umd.min.js
lucide.min.js
bootstrap.min.css
Then link to the local assets:
<link rel="stylesheet" href="/static/vendor/bootstrap.min.css">
<script src="/static/vendor/chart.umd.min.js"></script>
<script src="/static/vendor/lucide.min.js"></script>
Your application's static route serves them from the same origin. Keep vendor file versions and licenses documented and review updates when upgrading.
8. Organize JavaScript modules
A larger frontend can use native ES modules:
<script type="module" src="/static/js/main.js"></script>
static/js/main.js:
import { showMessage } from "./ui.js";
document.getElementById("hello").addEventListener("click", () => {
showMessage("Hello from Mojara!");
});
static/js/ui.js:
export function showMessage(text) {
document.getElementById("message").textContent = text;
}
These files are fetched separately by the browser. For bundled applications built with Vite or another frontend build tool, configure the final output under Mojara's public static directory.
Result
Your Mojara application can render HTML templates, load your stylesheets and scripts, use Lucide icons, display Chart.js charts, style forms with Bootstrap, and make asynchronous requests to backend routes.
Go back to Template rendering or continue to Sessions and cookies.