Every media control lives on the editor toolbar, and everything you insert comes out of your asset library — so uploading a file and placing it on a page are the same flow approached from two directions. Pick from the library and the file is already there; drag a file onto the canvas and it is uploaded, added to the library, and placed where you let go, in one gesture.
Each embed then has a settings dialog. The dialogs are generous; the published site is not. This page tells you, embed by embed, which fields survive the trip from the editor to a reader’s browser.
Insert Asset
Insert Asset on the toolbar opens the asset picker over the canvas. It lists everything in your library with a search box (matching the asset’s name), a type filter reading All Types / Images / Videos / Audio / Documents, and label filtering. Choosing an asset closes the picker and inserts it at the cursor.
What gets inserted depends on the asset’s type — you do not choose a block, the type chooses it for you:
| Asset type | What lands in the page | Then |
|---|---|---|
| Image | An image block | Alt text is pre-filled from the asset’s name; the width and height come from the original file |
| Video | A Cloudflare video player block | Playback options are set in the video dialog |
| Audio | An audio player block | The path and asset id are filled in for you |
| Document | An inline download link carrying the document’s name | Not a block — it lands in the sentence you are writing |
Everything the picker offers is already in the library, so the material you are inserting is documented on Asset Library.
Drag and drop
Drag a file from your desktop onto the canvas and let go: Leed uploads it, adds it to your library, and inserts it at the position under your pointer. The drop indicator between two blocks shows exactly where it will land.
Dropping the same file anywhere else in the CMS uploads it to the library without inserting it. Both routes need the asset:create privilege; without it the CMS attaches no drag listeners at all. The full behavior — MIME-type routing, the crop step for images, the size limits — is on Uploading by Drag and Drop.
Images
Click an image in the canvas and its gear opens Image Settings, which has two fields: Alt Text and Title.
Alt text is never optional. It is the sentence a screen reader speaks and the text a search engine reads, and Leed already wrote you a first draft — a vision model describes every image at upload time and you can regenerate it, as Uploading Images describes. Edit it to say what the image means in this context; do not clear it.
Title is different, and most of the time you should leave it blank. A title is not metadata — it turns the image into a <figure> with a visible <figcaption> on the published page, which the docs stylesheet then frames with a border. That is a design decision. Write one when the caption says something the surrounding prose does not: a state the reader must notice, a value that differs from the default, or the deliberate difference between two images shown side by side.
| Dialog field | Markdown | Required? | Default | Reaches the published site? | Notes |
|---|---|---|---|---|---|
| Alt Text | the text inside ![…] | Strongly recommended | The asset’s name | Yes | Written for you at upload by the vision model |
| Title | the quoted string after the URL | No | Empty | Yes — renders a <figure> with a visible caption | A visible design element, not free metadata |
| — | =WIDTHxHEIGHT appended to the alt text | No | The original file’s pixel size | Yes | Taken from the asset record; there is no dialog control |
| — | data-assetid | — | The asset id | Yes | Ties the placement back to the library record |
| — | data-responsiver="false" | — | Emitted for SVG only | Yes | Opts an SVG out of the responsive rewrite |
Sizing and the responsive rewrite are the site build’s job, not the editor’s: the build turns each image into a srcset of CDN variants, which Image Variants and Responsive Images explains.
Video
Video comes from your library, where Cloudflare Stream has already processed it — a freshly uploaded file is not insertable until that finishes, as Video, Audio and Document Assets sets out. Insert it from the asset picker, then open the widget’s gear for Cloudflare Video Settings: Autoplay, Show Controls, Loop, Muted, Poster Image URL and Start Time (seconds).
Ticking Autoplay ticks Muted for you, and the Muted label changes to read Muted (required for autoplay) — browsers refuse to autoplay a video with sound, so this is the dialog stopping you from shipping a player that silently never starts.
| Dialog field | Markdown parameter | Required? | Default | Reaches the published site? | Notes |
|---|---|---|---|---|---|
| — | videoId | Yes | From the asset | Yes | The Cloudflare Stream id; set when you pick the asset |
| — | assetId | Yes | From the asset | Yes | The Leed asset id |
| Autoplay | autoplay | No | Off | Yes — becomes autoplay=true on the player URL | Forces Muted on |
| Show Controls | controls | No | On | Yes | |
| Loop | loop | No | Off | Yes | |
| Muted | muted | No | Off | Yes | |
| — | allowFullscreen | No | On | Yes | No dialog control; on unless the markdown says otherwise |
| — | width / height | No | Unset | Yes | Carried from the asset when known |
| Poster Image URL | — | No | Empty | No | Shows in the editor’s preview only |
| Start Time (seconds) | — | No | 0 | No | Shows in the editor’s preview only |
| — | thumbnailTimestamp | No | Unset | Yes | Picks the poster frame, in seconds. No dialog control — only reachable in hand-written or imported markdown |
YouTube
YouTube Video on the toolbar opens Insert YouTube Video. It asks for a Video ID — the part after v= in a YouTube URL, not the whole URL — and then offers Title, Width, Height, Start Time (seconds), End Time (seconds) and seven checkboxes: Autoplay, Show Controls, Loop, Muted, Show Info, Show Related Videos and Modest Branding. The Insert button stays disabled until the Video ID is non-empty.
| Dialog field | Markdown parameter | Required? | Default | Reaches the published site? | Notes |
|---|---|---|---|---|---|
| Video ID | videoId | Yes | — | Yes | Becomes src="https://www.youtube.com/embed/<id>" |
| Title | title | No | Empty | No | The iframe’s title is hard-coded to YouTube video player |
| Width | width | No | 560 | Yes | Written only when it differs from the default |
| Height | height | No | 315 | Yes | Written only when it differs from the default |
| Autoplay | autoplay | No | Off | Partly | Adds autoplay to the iframe’s allow list; does not start playback |
| Muted | muted | No | Off | No | Ticked for you when you tick Autoplay |
| Loop | loop | No | Off | No | |
| Show Controls | controls | No | On | No | |
| Start Time (seconds) | startTime | No | 0 | No | |
| End Time (seconds) | endTime | No | 0 | No | |
| Show Info | showInfo | No | On | No | |
| Show Related Videos | rel | No | On | No | |
| Modest Branding | modestbranding | No | Off | No | |
| — | allowFullscreen | No | On | Yes | Always emitted; there is no control for turning it off |
Audio
An audio asset inserted from the picker arrives with its Audio Path and Asset ID already filled in — the two required fields of the Insert Audio dialog are not things you normally type. The dialog then offers Auto Play, Show Controls and Loop, and all three reach the reader.
| Dialog field | Markdown parameter | Required? | Default | Reaches the published site? | Notes |
|---|---|---|---|---|---|
| Audio Path | path | Yes | Filled by the picker, as /f/<assetId>/<filename> | Yes | Becomes the <source src> |
| Asset ID | assetId | Yes | Filled by the picker | Yes | Emitted as data-assetid |
| Auto Play | autoplay | No | Off | Yes | |
| Show Controls | controls | No | On | Yes | |
| Loop | loop | No | Off | Yes |
The site renders a plain HTML <audio> element with the fallback line Your browser does not support the audio element. — no custom player, no skin. Like video, an audio asset’s transcript can be inserted into the page from this dialog on Starter and up.
Iframes
Iframe on the toolbar opens Insert Iframe: URL (required), Title, Sandbox, Loading (Lazy or Eager), Referrer Policy (an eight-option list defaulting to Strict Origin When Cross Origin) and Allow Full Screen.
Leed injects nothing here. An option you leave blank is simply absent from the emitted <iframe> — so a blank Sandbox means no sandbox at all, not a safe default.
| Dialog field | Markdown parameter | Required? | Default | Reaches the published site? | Notes |
|---|---|---|---|---|---|
| URL | src | Yes | — | Yes | The only supported way to give the frame a URL |
| Title | title | No | Empty | Yes | Screen readers announce it — write one |
| Sandbox | sandbox | No | Empty | Yes | A space-separated permission list, e.g. allow-scripts allow-same-origin |
| Loading | loading | No | lazy | Yes | lazy or eager |
| Referrer Policy | referrerPolicy | No | strict-origin-when-cross-origin | Yes | Emitted lower-cased as referrerpolicy |
| Allow Full Screen | allowFullScreen | No | Off | Yes | Emitted as the bare allowfullscreen attribute |
| — | width / height | No | Unset | Yes | No dialog control; settable in markdown |
Forms
Form on the toolbar inserts a form block. The dialog is a single Form select listing every form in your workspace by name, with the hint Select the form to embed. The editor writes only the form’s id into the page.
At build time the block becomes the {{> leed/form }} Handlebars partial with that id, and the partial renders the real form — fields, validation and submission included. Placing a Form on a Page covers what the reader gets and where the submissions go.
Icons
Icon on the toolbar opens the icon chooser. Icons are inline, so they sit inside a sentence rather than owning a block: click to open settings.
An icon’s color is set from the icon’s own color picker, which stores a Tailwind text color and a dark-mode twin — those come out as ordinary text-… and dark:text-… classes and render correctly.
| Dialog field | Markdown | Required? | Default | Reaches the published site? | Notes |
|---|---|---|---|---|---|
| Icon (chooser) | fa-solid fa-gear — the style prefix and icon name | Yes | — | Yes | An icon with no style prefix is not written at all |
| Color (picker) | text-<color>-<depth> | No | Unset | Yes | An ordinary Tailwind class |
| Dark color (picker) | dark:text-<color>-<depth> | No | Unset | Yes | Stored alongside the light color |
| — | any other class name | No | — | Yes | Appended to the class list verbatim |
The full shortcode syntax, including the style prefixes and where icon names come from, is on Embeds and Icons.
From the file to what a reader receives
Nothing you set in a dialog is applied in the browser directly. The editor stores your choices on the block, the page serializes to Leed Markdown when it publishes, and the site build turns each embed into HTML — which is where the fields in the tables above are either honored or quietly dropped.
flowchart TD DROP["Drag a file onto the canvas"] --> UP["Upload"] PICK["Insert Asset → asset picker"] --> LIB UP --> LIB["Asset library record<br/>AI alt text · transcript · Stream processing"] LIB --> NODE["A block in the editor<br/>image · video · audio · download link"] YT["YouTube · Iframe · Form · Icon<br/>toolbar dialogs"] --> NODE NODE --> DLG["Settings dialog<br/>options stored on the block"] DLG --> MD["Leed Markdown<br/>written when the page publishes"] MD --> BUILD["Site build renderer"] BUILD --> IMG["An img tag with a responsive srcset"] BUILD --> IFR["An iframe — YouTube keeps only<br/>src · width · height · allowfullscreen"] BUILD --> AUD["An audio tag with a text fallback"] BUILD --> FRM["The form partial"] DLG -. "poster · start time · most YouTube options" .-> LOST["Stored, never emitted"]
The delivery side is automatic and needs nothing from you: images are resized and served in modern formats from the CDN, and video is streamed adaptively. What you choose in the editor is composition; what the reader’s connection gets is the build’s problem.
Every button named here is cataloged with its shortcut on Editor Toolbar Reference, and the non-media dialogs behind a block’s gear — alerts, collapsibles, code blocks, tab groups — are on Block Types and Block Settings.