The mount() API
Every app so far has run through marko-run: the server renders your templates to HTML, ships it, and the browser takes over. This one has no server at all. Marko can render a template entirely in the browser — no SSR, no marko-run, just a plain Vite app that builds to static files a CDN could serve.
The setup is small. index.html has an empty mount point and loads one
script:
<div id="app"></div><script type="module" src="/src/main.js"></script>src/main.js is the entry — it imports a .marko template and renders it.
And vite.config.js uses the Marko plugin in unlinked mode
(marko({ linked: false })): that’s the switch that tells it to build a
browser-only bundle instead of the server-plus-client pair marko-run
produces.
Mounting the template (your job)
A Marko template compiled for the browser has a .mount() method:
Template.mount(input, node);It builds the template’s reactive DOM and drops it into node, and
input becomes the template’s input. Open src/main.js and mount App
into the #app element:
import App from "./app.marko";
App.mount({ name: "Marko" }, document.getElementById("app"));That’s the whole bootstrap. Save, and the preview springs to life — the
heading and a working counter, rendered client-side, with no HTML ever
coming from a server. The { name: "Marko" } you passed is the template’s
input; the counter’s reactivity works exactly as it does everywhere else
in Marko.
That’s Marko with no server: a template, a mount point, and one .mount()
call — the same components and reactivity you already know, rendered
entirely in the browser.
- Installing dependencies
- Starting dev server