Skip to content

Embeds or runtime?

Mountly does two jobs. They share adapters and a lifecycle underneath. Above that they share nothing: different APIs, different builds, and a different ask of the person on the other end. Pick your column and read only that one.

Embeds Runtime
The question it answers “Another team wants my component on their page” “My page should pay for JavaScript only when the user needs it”
Who owns the page Someone else You
The consumer does Adds one <script> and writes a tag Runs mountly: an import map, or a bundler
You write A component and a prefix A component, a widget, a feature
You build with defineElementsConfig defineMountlyWidgetConfig, mountlyRemote
The API embed.js, generated embed.d.ts attach, installRuntime, <mountly-feature>, data-mountly
Framework copies One per distribution, bundled in One per page, shared through the import map
Start at Script-tag embeds Quick start

There is a third door: MCP Apps, where the host is Claude or ChatGPT rather than a web page. Same components, its own toolchain (mountly-mcp), and neither column above applies.

Most people arrive asking the first question. An embed asks less of the other team: no install, no import map to agree on, no framework version to coordinate, no runtime to adopt. You build a tag, they write it:

vite.config.ts
export default defineElementsConfig({ prefix: "acme", elements: "src/elements/*.tsx" });
<script type="module" src="https://ui.acme.com/payments/1.2.0/embed.js"></script>
<acme-payments-summary balance="1250" currency="GBP"></acme-payments-summary>

That is the whole integration. The props type is the contract, and the other team installs nothing.

Move to the runtime when the host runs mountly

Section titled “Move to the runtime when the host runs mountly”

The runtime covers what embeds cannot: one page, many widgets, one shared framework instance. Every embed distribution bundles its own copy of React. For one component on a foreign page you should pay that. For eight widgets from four teams on a page you control you should not, and the host adopts mountly instead: an import map pins one React, widgets ship as peer builds, and <mountly-feature> or data-mountly places them.

That costs more to adopt, and Choosing an architecture walks its stages. Do not start there.

A component is a component. The same source can ship as an embed for outside teams and import directly into your own app, with no second authoring model and no flag:

import PaymentsSummary from "@acme/payments/PaymentsSummary";

The embed build registers custom elements; the import registers nothing. Do not teach one consumer both. Pick the column that matches who owns their page.