Comment

Comment by amaury_bouchard

Thanks! The short answer: µJS doesn't try to be a DSL in HTML attributes.

Here's what I deliberately left out compared to Turbo (~25KB gzip) and htmx (~16KB gzip):

- No client-side template/extension system. htmx has a full extension API, header-based control flow (HX-Trigger, HX-Redirect, HX-Reswap...), and dozens of response headers the server can use to command the client. µJS has 5 custom headers total; the server returns HTML, the client renders it.

- No CSS selector-based targeting in attributes. htmx lets you write hx-target="closest tr", hx-target="find .result", hx-target="next div" with a mini query language. µJS uses plain CSS selectors only (mu-target="#id"), no traversal keywords.

- No built-in transition/animation classes. htmx adds/removes CSS classes during swaps (htmx-settling, htmx-swapping, htmx-added) with configurable timing. Turbo has turbo-preview, transition classes, etc. µJS defers to the native View Transitions API: zero animation code in the library, and it falls back silently.

- No client-side cache or snapshots. Turbo keeps a page cache for "instant" back-button rendering and manages preview snapshots. µJS stores only scroll position in history.state and lets the browser's own cache + fetch() handle the rest.

- Patch mode simpler than Turbo Frames. Turbo has <turbo-frame>, a custom element with lazy-loading, src rewriting, and frame-scoped navigation. µJS handles multi-fragment updates via patch mode (mu-mode="patch") with regular HTML elements. No custom elements, no frame concept. It's simpler but it works perfectly.

- No request queuing or throttling. htmx has hx-sync with queuing strategies (queue, drop, abort, replace). µJS simply aborts the previous in-flight request. One request at a time per navigation.

- No form serialization formats. htmx supports JSON encoding (hx-encoding), nested object serialization, etc. µJS uses the browser's native FormData for POST and URL params for GET. That's it.

- No JavaScript API surface to speak of. htmx exposes htmx.ajax(), htmx.process(), htmx.trigger(), event details, etc. µJS exposes mu.init(), mu.fetch(), mu.render(), and a few setters and a few events. The goal is that you shouldn't need the JS API — the HTML attributes should be enough.

What I kept: the features that cover 90% of real-world use cases. AJAX navigation, 8 injection modes, multi-fragment patch, morphing (via Idiomorph), SSE, prefetch, forms with all HTTP verbs, triggers with debounce/polling, progress bar, history/scroll management. Just without the layers of abstraction around them.

The philosophy: if the browser already does it (View Transitions, FormData, fetch, AbortController, history API), don't reimplement it.

No comments yet

Be the first to share your thoughts.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton