HMPL.js: Server-Oriented, Customizable Templating for JavaScript
Discover HMPL.js, a lightweight JavaScript library for server-driven, customizable templates. Build dynamic UIs with minimal JS, leveraging Fetch API, JSON5, and DOMPurify for efficient, secure, and flexible web development.

Server-oriented customizable templating for JavaScript
π Website β’ π Docs β’ π₯οΈ Demo Sandbox β’ βοΈ Examples
Introduction
HMPL.js offers exceptional flexibility for building server-driven templates with minimal JavaScript. Its block-based syntax, customizable fetch requests, and built-in support for forms, events, and time-based syncing enable the delivery of dynamic user interfaces without the overhead of heavy frameworks. HMPL seamlessly integrates with JSON5 for expressive object syntax and DOMPurify for secure HTML rendering, all packaged in just a few kilobytes.
Example
<div>
{{#request src="/api/my-component.html"}}
{{#indicator trigger="pending"}}
<p>Loading...</p>
{{/indicator}}
{{/request}}
</div>
Try HMPL online at: hmpl-playground
Basic usage
HMPL.js allows you to create dynamic components that interact directly with your server.
import hmpl from "hmpl-js";
const templateFn = hmpl.compile(`<div>
<button data-action="increment" id="btn">Click!</button>
<div>Clicks: {{#request src="/api/clicks" after="click:#btn"}}{{/request}}</div>
</div>`);
const clicker = templateFn(
({
request: {
event
}
}) => ({
body: JSON.stringify({
action: event.target.getAttribute("data-action")
})
})
).response;
document.querySelector("#app").append(clicker);
Explain this!
Let's break down the basic usage example:
import hmpl from "hmpl-js"; // Import the HMPL library
// Compile an HMPL template with dynamic behavior
const templateFn = hmpl.compile(`<div>
<button data-action="increment" id="btn">Click!</button>
<!-- This div will update with the click count from /api/clicks -->
<div>Clicks: {{#request src="/api/clicks" after="click:#btn"}}{{/request}}</div>
<!-- Also, you can write in short: {{#r src="..."}}{{/r}} -->
</div>`);
// Generate a response handler for the template
// In the original object, we will have the following: { response: div, status: 200 }
const clicker = templateFn(
({
request: {
event
}
}) => ({
// Send a JSON payload with the action from the button's data attribute
body: JSON.stringify({
action: event.target.getAttribute("data-action")
})
})
).response;
// Append the dynamically generated element to the #app container
document.querySelector("#app").append(clicker);
In this example, we create a dynamic clicker component where pressing a button triggers a server request to fetch the current click count. A key advantage of this approach is that HMPL can retrieve not only simple data (like text) but also entire components and even full pages from the server.
Usage with DOM
For scenarios where you prefer not to use JavaScript for dynamic mounting, the hmpl-dom module allows for declarative integration.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Example</title>
</head>
<body>
<main>
<template hmpl>
<div>
{{#request src="/api/my-component.html"}}
{{#indicator trigger="pending"}}
<p>Loading...</p>
{{/indicator}}
{{/request}}
</div>
</template>
</main>
<script src="https://unpkg.com/json5/dist/index.min.js"></script>
<script src="https://unpkg.com/dompurify/dist/purify.min.js"></script>
<script src="https://unpkg.com/hmpl-js/dist/hmpl.min.js"></script>
<script src="https://unpkg.com/hmpl-dom/dist/hmpl.min.js"></script>
</body>
</html>
With hmpl-dom, components fetched from the server are automatically mounted into the DOM, eliminating the need for manual JavaScript manipulation.
Why HMPL?
By leveraging HMPL's templating capabilities, you can significantly reduce your application's bundle size. Its full customization of requests based on the modern fetch standard, coupled with essential features for modern applications (such as request indicators, event-driven sending, automatic body generation for forms, and caching), and a concise object syntax in markup, facilitate highly efficient server-client interaction. Compare app sizes below:

HMPL also serves as an excellent alternative to popular tools like HTMX and Alpine.js.
Features
- Customizable: Send tailored requests to the server when receiving UI updates.
- Memory Preserving: Dramatically reduce client-side file sizes.
- Based on Fetch API: Utilizes a modern standard, moving beyond
XMLHTTPRequest. - Server-oriented: Interact directly with the server through markup and minimal JavaScript.
- Generate thousands of DOM nodes from a single template: Efficiently handle large components on both server and client.
- Simple: Obtain ready-made UI from the server by writing just a few lines of familiar object syntax.
- Protected from XSS attacks: Safely render incoming server HTML by enabling built-in sanitization with DOMPurify.
- Flexible: Adaptable to almost any project, supporting both script-based integration and
.hmplfiles. - Integrated with JSON5: Enjoy flexible object syntax, as in vanilla JS, backed by a widely used and reliable parser.
- Small bundle size: A rich set of functionalities packed into just a couple of kilobytes.
Installation
HMPL can be installed using several methods. As a simple JavaScript file, it can be connected via a standard script tag or through the import construct in environments that support it (e.g., Webpack, Parcel builds).
Note: Starting with version 2.2.0, the JSON5 module is required, and from version 2.2.5, the DOMPurify module is also necessary. The simplest way to include these is via a CDN.
Package Manager
Install HMPL via npm or other package managers:
npm i hmpl-js
Minified and regular JavaScript files can be found in node_modules/hmpl/dist.
CDN
Connect HMPL and its dependencies via a CDN, which provides access to the npm package files through a link:
<script src="https://unpkg.com/json5/dist/index.min.js"></script>
<script src="https://unpkg.com/dompurify/dist/purify.min.js"></script>
<script src="https://unpkg.com/hmpl-js/dist/hmpl.min.js"></script>
<!-- You might also add integrity="..." crossorigin="anonymous" for security -->
Popular CDN providers include unpkg, skypack, and others. unpkg is used in examples due to its popularity and concise URLs.
Through the starter template project
Get started quickly with a Vite starter project:
npx degit hmpl-language/hello-hmpl-starter hello-hmpl
This provides a solid foundation for building web applications.
Official Tools
VS Code Extension
Syntax highlighting and development tools for HMPL.
Vite Plugin
Seamless .hmpl file integration with Vite.
Webpack Loader
Compile
.hmpl files directly within Webpack projects.
We encourage and welcome community-developed tools as well!
Community support
The documentation provides comprehensive information on how the HMPL template language functions. For any questions regarding HMPL, you can utilize the following resources:
- GitHub: Ask questions in the discussion and issues sections.
- Discord: Join the "support" channel for assistance.
- π (Twitter): Follow for interesting updates and discussions related to the template language and more.
You can also post your questions on Stack Overflow and reference the resources mentioned above.
Contribution
Refer to our Contributing Guide for detailed steps on how to contribute to the project. A heartfelt thank you to all individuals who have already contributed to HMPL or its related projects!
Star History
Roadmap
Explore the project's roadmap to see plans for future development.
License
Released under the MIT License.
π Star this repo β’ π» Try HMPL.js β’ π¬ Join Discord
This project thrives on the valuable contributions of many amazing community developers!