mountly
Load rich UI only when the user actually needs it.
A small frontend runtime that splits code at the feature level and activates widgets on intent — hover, click, focus, viewport, or idle. No microfrontend orchestrator. No new component model. No host-app rewrite.
Modern web apps ship too much JavaScript upfront.
Component libraries load everything at once. Microfrontends are operationally heavy. Framework lazy-loading lacks standardised interaction patterns. There’s no unified system for “load rich UI only when the user actually needs it”.
Before mountly
- Payment widget
- Video player
- Image lightbox
- Analytics panel
- Chat widget
All shipped on first paint. Slow TTI, heavy bundle.
After mountly
- Page shell (light)
- User hovers → load module
- → fetch data in parallel
- → mount into shadow DOM
Fast TTI. Each widget pays only on intent.
Six ways to say “now”.
A trigger is the signal that moves a feature from idle to preload to
mount. Pick the one that matches user intent — or compose your own with a plugin.
requestIdleCallback to preload during quiet moments.One state machine, five states. The same shape on every framework.
Every feature moves through the same sequence regardless of trigger or framework. You can hook into any phase, abort in flight, and unmount cleanly.
A widget. A feature. A trigger. Three lines you’ll write.
Components stay components. The adapter wraps them as widgets. createOnDemandFeature adds the on-demand lifecycle. attach wires it to a DOM element.
import { createWidget } from "mountly-react";import SignupCard from "./SignupCard.tsx";import styles from "./SignupCard.css?inline";
// 1. Wrap a component as a framework-agnostic widgetexport default createWidget(SignupCard, { styles });import { createOnDemandFeature } from "mountly";
// 2. Add the on-demand lifecycle around a widgetconst signup = createOnDemandFeature({ moduleId: "signup-card", loadModule: () => import("./signup-card.js"), render: ({ mod, container, props }) => mod.mount(container, props),});
// 3. Attach it to a DOM trigger — preload on hover, mount on clicksignup.attach({ trigger: document.querySelector("#cta")!, preloadOn: "hover", activateOn: "click",});Performance benefits of microfrontends. None of the orchestration.
| Approach | Initial bundle | User experience | Complexity |
|---|---|---|---|
| Traditional SPA | Large | Slow first paint, fast after | Low |
| Framework code-splitting | Medium | Better, but route-bound | Medium |
| Microfrontend orchestrators | Variable | Good, runtime-coordinated | High |
| mountly | ~9 KB core | Instant shell, features on intent | Low |
One runtime, three adapters, one design preset.
createWidget(Component, { styles }).mountly-vueVue adapter — same surface, createApp under the hood.mountly-svelteSvelte adapter — auto-detects v4 class API and v5 functional API.mountly-tailwindOptional Tailwind v4 design preset. Tokens shared with the runtime.