HTM (Hyperscript Tagged Markup)
JSX-like syntax in plain JavaScript using tagged template literals, no transpiler needed
Repository Health
Technical Analysis
HTM (Hyperscript Tagged Markup) brings JSX-like syntax to plain JavaScript using standard Tagged Template Literals, so developers can write React/Preact-style markup directly in the browser without a build step, then optionally compile it away for production via a Babel plugin.
Created by Preact author Jason Miller, HTM ships at under 600 bytes standalone (under 500 bytes with Preact bindings) and works in all modern browsers without transpilation, while also improving on JSX ergonomics with optional quotes, component end-tags, and multiple root elements.
What You Get
- A tagged-template parser (
htm) that converts JSX-like markup intocreateElement/hyperscript calls - Off-the-shelf bindings for Preact (
htm/preact) and React (htm/react) sharing a template cache across modules - A companion
babel-plugin-htmfor compiling HTM syntax away entirely at build time, producing zero runtime bytes - JSX ergonomic improvements: optional HTML attribute quotes, component end-tags (
<//>), multiple root elements/fragments, and HTML comment support - A
htm/minibuild (~450 bytes) for size-constrained environments
Common Use Cases
- Prototyping React/Preact components directly in the browser via CDN import, with no build tooling required
- Adding JSX-like ergonomics to small scripts or CodePen-style demos where setting up Babel/webpack is overkill
- Shipping ultra-lightweight component syntax to size-sensitive projects (widgets, embeds) where every kilobyte matters
- Compiling HTM syntax to zero-runtime-cost hyperscript calls at build time via
babel-plugin-htmfor production apps
Under The Hood
Architecture: The published htm package’s runtime entry point (src/index.mjs, ~29 lines) is a thin caching wrapper around build.mjs’s build/evaluate functions — it memoizes the parsed template structure per unique template-literal statics array (using a WeakMap-style CACHES map keyed by the bound hyperscript function), so repeated renders of the same template skip re-parsing and only re-evaluate the dynamic interpolated values. constants.mjs toggles a MINI build flag that swaps the caching regular function for the raw build function directly, trading the parse-cache for a smaller bundle. The repo is a monorepo (packages/) also housing babel-plugin-htm, which reuses the same parser to shift the tagged-template-to-hyperscript conversion to build time, eliminating runtime parsing cost entirely. Tech Stack: Distributed as dual ESM/UMD/CJS builds (dist/htm.mjs, dist/htm.umd.js, dist/htm.js) with hand-written TypeScript declarations, and integration entry points for Preact and React that pre-bind the parser to each library’s element-creation function so consumers import a ready-to-use html tag. Code Quality: The test suite (~1,400 lines across test/) is proportionally large relative to the terse core implementation, reflecting the outsized edge-case surface of parsing arbitrary JSX-like syntax out of template literals (spread props, self-closing tags, fragments, boolean attributes); however, the project has had no commits since 2024, so it is effectively feature-frozen rather than under active development. API Design: The public API is a single default export — a template-tag function you bind to your renderer’s createElement (htm.bind(h)) — making integration with any hyperscript-style library a one-line operation, and the Preact/React sub-exports remove even that step for the two most common targets.
Used by 2 apps in this directory
AI Engineer Coach
Developer Tools
A VS Code extension that reads your local AI coding session logs and turns them into actionable insights — anti-pattern detection across 45 rules, output tracking by model and harness, and skill discovery, with no data leaving your machine.
marimo
Developer Tools · Data Engineering
A reactive Python notebook that eliminates hidden state, runs reproducibly, and deploys as a web app or script — stored as pure Python, built for the AI era.