HTML is a native image format, hear me out

yeargun1 pts1 comments

HMML - HyperMedia Markup Language

composability, not pixels

The next thing a model generates isn’t an image.<br>It’s a document.

An image flattens everything into one frozen raster. HMML keeps the pieces - vector, text, raster, 3D, motion - composable and editable, created at the grain of a node, not a 1024-grid of guesses.

01<br>Composable, not flattened<br>A photo, an icon, a chart, a 3D scene - an image crushes them into one raster. HMML keeps each as itself: layered, addressable, recomposable.

02<br>Fine-grained primitives<br>Create and edit at the grain of an element, a transform, a keyframe - change one node, not the whole render. Diff it, version it, remix it.

03<br>Editable, not frozen<br>Restyle, re-localize, animate after the fact. Generated output that stays source - not a screenshot you can only regenerate.

04<br>Native to models<br>Models already write HTML, CSS and SVG. HMML just seals that output, with raw media, into one portable contract - a ~2 KB reader opens it anywhere.

Will models evolve to emit this directly? Maybe. Maybe not. But “image” is already an overloaded word - photo, icon, chart, scene, animation, all crushed into one frozen raster. HMML un-conflates it, and earns its use cases either way. Or maybe pixels were fine all along. Let’s see.

then / now

You don't build the scene. You mount it.

Today you hand-wire layout, styles, state and a folder of assets around a couple of flat AI images. With HMML the model ships the whole scene as one file - your app just fetches it, decodes, and mounts it into a div . All the complexity downloads inside the .hmml.

today - you assemble every piece by hand<br>"product"><br>"ai/hero-1.png"> "ai/hero-2.png"> // AI's whole job<br>"copy"><br>you hand-write this<br>...and this. and the alt text.<br>"addToCart()">Buy

.product{ display:grid; gap:24px } /* +40 lines */<br>"layout.js"><br>hydrate(); wireCarousel(); track()

next - fetch &middot; decode &middot; mountscene = 100% AI<br>"scene"> // the mounting div

"module"><br>import { unpack } from "@eddocu/hmml"<br>const bytes = await fetch("scene.hmml").then(r => r.arrayBuffer())<br>const doc = await unpack(new Uint8Array(bytes)) // decode<br>scene.innerHTML = doc.toHTML() // mount

// one file = layout + media + motion + logic

what you can make

An image you can compose.

Arrange images in 2D or 3D, layer them, animate them - every piece stays editable, iterable and recomposable into new visuals. The scene below is just one example: a drifting cloud of images and SVGs, decoded live from a single .hmml. Move your pointer over it.

one .hmml · … · a live scene

Each one is a single .hmml.

Vector, raster, 3D and text that rewrites itself - decoded right now, no network, no dependency.

the contract

bits & bytes & a contract.

A PNG-style signature, then self-describing chunks. Markup stays text; images stay raw. Unknown chunks are skipped - it grows without breaking. Full spec →

89 'H' 'M' 'M' 'L' 0D 0A 1A 0A · major · minor · codec

MARK<br>the markup - HTML / CSS / SVG / JS, gzip-able text

RSRC<br>a resource - id + mime + raw bytes (no base64)

META<br>JSON metadata

ENDF<br>end marker · markup points at resources with hmml:

use it

Two calls.

// ENCODE — pack(html) → one .hmml (a Uint8Array you store or send)<br>// · lifts every data: image out of the HTML into raw bytes (no base64)<br>// · gzips the HTML/CSS/JS and frames it all as one binary blob<br>const bytes = await pack(html)

// DECODE — unpack(bytes) → the document back, anywhere a browser runs<br>// · reads the markup + the raw images out of the blob<br>// · toHTML() re-stitches them into renderable HTML you can mount<br>const doc = await unpack(bytes)<br>el.innerHTML = doc.toHTML() // (or doc.createObjectUrls() for blob: URLs)

defined

image, /ˈɪm.ɪdʒ/ noun

one .hmml · … · a dictionary entry

hmml scene html image bytes markup

Related Articles