What is Markup?
Markup is a JavaScript reactive templating system built to simplify how you build Web user interfaces using web standards with minimal enhancements to the native web APIs as possible.
It consists of 3 main APIs with additional utilities to simplify things even further:
htmlA JavaScript tagged function that allows you to represent the DOM using template literal strings.stateA simple state tracking API that lets you define reactive data however you want.effectA straightforward way to define things that need to happen when certain states change.
Why do we need another tool?
Modern web development has become heavily reliant on complex build steps, compiler configuration, and massive framework dependencies. Often, all you want to do is build a reactive interface, but you end up having to set up Vite, Babel, Webpack, Svelte, or React just to get basic state reactivity.
Markup exists to solve this pain point. It bridges the gap between raw, tedious DOM manipulation and heavy component frameworks. By utilizing modern JavaScript primitives—specifically template literals and functions—Markup provides clean, declarative, and surgically precise reactivity without any build steps.
Compare how you build a simple counter.
The Tedious Vanilla Way
1let count = 02 3// tedious DOM definition and manipulation4const p = document.createElement('p')5p.textContent = `count: ${count}`6 7const btn = document.createElement('button')8btn.type = 'button'9btn.textContent = 'count up'10 11// limiting event driven12btn.addEventListener('onclick', () => {13 count += 114 p.textContent = `count: ${count}`15 16 if (count > 10) {17 alert('You counted passed 10!')18 }19})20 21document.body.append(p, btn)The Markup Way (Simple & Reactive)
1// reactive data2const [count, updateCount] = state(0)3 4// data driven5effect(() => {6 if (count() > 10) {7 alert('You counted passed 10!')8 }9})10 11const countUp = () => {12 updateCount((prev) => prev + 1)13}14 15// reactive DOM/templates16html`17 <p>count: ${count}</p>18 <button type="button" onclick="${countUp}">count up</button>19`.render(document.body)Core Concepts
1. Functions for Lazy Evaluation
Reactivity in Markup is powered by native JavaScript functions. Since functions represent lazy evaluations, they can be run whenever their underlying state changes. Wrapping your values or templates in functions is the secret behind Markup's surgical DOM updates.
2. Tagged Template Literals
Markup uses the standard html tagged template literal to represent the DOM. No JSX parser, no proprietary template syntax, and no Virtual DOM. What you write is parsed directly into native HTML templates and updated surgically.
Key Benefits
- 🚀 Zero Build Step: No compilers, no bundlers, no npm install required to get started. Drop the CDN link into a
<script>tag and start coding. - ⚡ Surgical DOM Updates: No Virtual DOM diffing. Markup target-updates only the specific nodes and attributes that changed.
- 📦 Ultra Lightweight: At only 7.6KB gzip (18KB uncompressed), it is perfect for micro-frontends, widgets, prototypes, and lightweight web apps.
- 🔌 Standard Web Components: Easily integrates with Web Components to provide reactive rendering and simplified lifecycle management.