Images in pages
Bundle images with a page from the browser, or host them over MCP with add_page_image, and reference them by URL.
A page keeps its images as hosted assets and references them by URL, instead of as giant inline base64 blobs that bloat the HTML and can hit your plan's page-size limit. There are two ways to get images into a page: dropping them in the browser, or hosting them over MCP.
From the browser
When you create a page from an HTML file (on the dashboard) or replace one (from its settings), drop the HTML file together with its images. You can:
- select the HTML file and its image files together, or
- drag the HTML file and its images onto the upload box at once, or
- drag the whole folder, which keeps subfolder paths like
images/hero.png.
Any relative image reference in the HTML is then rewritten to its hosted asset URL automatically, so the page renders exactly as it did on your machine. For example, a file that contains:
<img src="hero.png">
<img src="images/cat.jpg">publishes with each src pointing at a hosted /api/page-assets/... URL.
If an image the HTML references was not included in the upload, the page still publishes, and you get a notice with a count of the images that could not be matched, so you can re-upload with them included.
From an AI client (MCP)
Call add_page_image with the page's id and either a public
image url (which is fetched server-side) or the raw dataBase64 bytes plus a
contentType. It stores the image and returns a hosted URL. Drop that URL into
an <img src="..."> in the page with create_page, update_page, or
patch_page.
This is the natural flow for an agent, which writes its own HTML and just needs somewhere to host each image. There is no relative-path bundling over MCP; use the URL the tool returns.
What gets rewritten
Rewriting on browser upload only touches relative references, and only in the attributes that load an image:
<img src>and<img srcset><source src>and<source srcset>inside a<picture>
References that already point somewhere are left untouched: a full http(s)://
URL, a protocol-relative //host/... URL, a data: URI, and an in-page #
anchor. Escaped example text (such as <img src="hero.png"> shown inside a
code block) is left alone too, since only real elements are rewritten.
Supported formats and limits
Page images are raster only (PNG, JPEG, GIF, WebP) and up to 4 MB each. SVG is not accepted, because an SVG served from the app origin could run script.
The image size limit is per image; your plan's page-size limit still applies to the HTML document itself.
Markdown pages
Image bundling applies to HTML uploads only. A Markdown page has no bundled asset
folder to resolve a relative path against, so its images must already be an
absolute http(s) URL or a data: URI. To host a Markdown page's images, upload
them with add_page_image first and reference the URL it returns.
Where images are served
Each asset is served from /api/page-assets/<id>/<name>. The <id> is an
unguessable token that grants access; the <name> at the end is decorative, to
keep the URL readable. Assets are stored privately and streamed through this
gated route, and they belong to the page rather than to a single version, so an
image keeps working even if you roll the page back to an earlier version that
still references it.