Static HTML reference.
Complete reference for the @inlinecms/loader script-tag drop-in — script attributes, editable element attributes, field types, built-in components, and runtime behavior.
@inlinecms/loader turns any HTML page into an editable one with a single <script> tag. It reuses @inlinecms/core for content fetch/hydrate/publish and sessions, and adds a small vanilla DOM binder on top — no framework, no build step. The heavy React editor chrome is loaded lazily and only for authenticated editors, so visitors stay React-free.
For a step-by-step setup, see the Static HTML quick start.
The script tag
Section titled “The script tag”<script src="/inlinecms.js" data-api-key="your-project-key" data-api-url="https://cms.yourdomain.com" data-page-id="/about" data-access="handoff" data-debug></script>Script attributes
Section titled “Script attributes”| Attribute | Required | Description |
|---|---|---|
data-api-key | Yes | Project API key. The loader does nothing (and logs an error) without it. |
data-api-url | No | API base URL. Set this when self-hosting; defaults to the hosted API. |
data-page-id | No | Override the page ID. Defaults to the page’s path (window.location.pathname). |
data-access | No | How editors authenticate: handoff (default), manual, or cookie. See Access modes. |
data-debug | No | Presence enables verbose console logging. |
Hosting the bundle
Section titled “Hosting the bundle”The loader ships as two files:
| File | Loaded by | Contains |
|---|---|---|
inlinecms.js | Every visitor | The lightweight DOM binder + content hydration. No React. |
inlinecms-editor.js | Editors only | The React editor chrome (toolbar, popovers, gallery dialog). |
Host both in the same directory. The src of your script tag can be named anything, but the loader resolves the editor chrome as inlinecms-editor.js as a sibling of that src, and injects it lazily the first time an editor is present. Plain visitors never download it.
Editable element attributes
Section titled “Editable element attributes”Add these to any element on the page.
| Attribute | Description |
|---|---|
inline-cms | Marks the element editable. Required to bind it. |
inline-cms-key | Stable key the stored value is bound to. Strongly recommended — see Key resolution. |
inline-cms-fingerprint | Alternate key (e.g. injected by a build step). Used if inline-cms-key is absent. |
inline-cms-type | Override the inferred field type (e.g. force a <div> to text). |
inline-cms-label | Human label shown in the editor’s active-element chip and content list. |
<h1 inline-cms inline-cms-key="home-title">Welcome</h1><div inline-cms inline-cms-key="home-intro" inline-cms-type="richtext"> <p>Formatted <strong>content</strong> lives here.</p></div><img inline-cms inline-cms-key="home-hero" inline-cms-label="Hero photo" src="/hero.jpg" />Field types
Section titled “Field types”The field type is inferred from the element’s tag name and decides how the field is edited. Override it with inline-cms-type.
| Inferred type | Tags |
|---|---|
text | h1–h6, p, span, label, caption, figcaption, dt, dd, li, td, th |
richtext | div, section, article, aside, blockquote, main |
image | img, picture, figure |
video | video, source |
url | a |
date | time |
number | meter, progress |
Any other tag falls back to text. The full set of assignable types is text, richtext, image, video, url, number, boolean, date, select, multiselect.
text and richtext elements become contenteditable in edit mode, and their sanitized innerHTML is stored — so inline formatting (bold, italic, links) is preserved, not flattened to plain text.
Key resolution
Section titled “Key resolution”When the loader binds an element, it resolves its key in this order:
inline-cms-keyinline-cms-fingerprint- A structural fallback derived from the element’s position (e.g.
auto:#main/p:2), with a console warning.
The structural fallback survives content edits but is fragile to layout changes, so always set an explicit inline-cms-key for anything you intend to keep. Duplicate keys on a page collide and log a warning.
Built-in components
Section titled “Built-in components”Render a built-in component by tagging a container with inline-cms-component and providing a JSON inline-cms-config:
<div inline-cms-component="gallery" inline-cms-key="home-hero" inline-cms-config='{ ... }'></div>| Attribute | Description |
|---|---|
inline-cms-component | The component name. Currently: gallery. |
inline-cms-key | Stable key the published config is bound to. |
inline-cms-config | JSON fallback config. Rendered until a config is published — also serves as author-provided SEO markup. |
The loader renders the component to static HTML from the published config (falling back to inline-cms-config). It re-renders automatically whenever the config is saved.
gallery
Section titled “gallery”A media gallery — the framework-neutral version of the React SDK’s <InlineHeroImageContainer>. The inline-cms-config is a JSON object:
| Field | Type | Description |
|---|---|---|
media | { url, type, caption? }[] | The media items. type is "image" or "video". |
defaultUrl | string | Which media URL renders as the large primary tile. |
layoutStyle | string | Layout preset: "1-4" (default), "single", "feature-stack", "mosaic". |
rounded | boolean | 16px corner radius around the gallery. Default true. |
useBuiltInStyling | boolean | When false, emit only tiles + class hooks and let your CSS own layout. Default true. |
containerClass | string | Extra class on the container, alongside the built-in inlinecms-hero. |
itemClass | string | Extra class on each tile, alongside inlinecms-hero__tile. |
<div inline-cms-component="gallery" inline-cms-key="home-hero" inline-cms-config='{"layoutStyle":"1-4","rounded":true,"media":[ {"url":"/img/1.jpg","type":"image","caption":"Garden terrace"}, {"url":"/img/2.jpg","type":"image"}, {"url":"/img/3.jpg","type":"image"} ],"defaultUrl":"/img/1.jpg"}'></div>Editing. In edit mode an Edit gallery pill appears on the component; it opens the same media dialog the React SDK uses (add/remove/reorder/caption media, choose the default tile, layout and class options). Saving writes the config back and re-renders the gallery in place.
View mode. When not editing, clicking a tile opens a fullscreen lightbox (counter, prev/next, thumbnails, keyboard nav, captions). It’s a vanilla viewer built into inlinecms.js, so visitors get it without React. Set "useBuiltInLightbox": false in the config to disable it.
Class hooks
Section titled “Class hooks”Both renderers emit the same class names, so a host stylesheet targets one set of hooks regardless of which adapter rendered the page:
| Class | Element |
|---|---|
inlinecms-hero | Gallery container |
inlinecms-hero__tile | Each image/video tile |
inlinecms-lightbox | Lightbox backdrop (plus __header, __counter, __close, __stage, __nav, __media, __caption, __thumbs, __thumb) |
Access modes
Section titled “Access modes”Set with data-access.
| Mode | Behavior |
|---|---|
handoff (default) | Visitors see a plain page. Editors arrive from the dashboard’s “Enable editing” action with a one-time, origin-bound token in the URL; the loader exchanges it for a session. No on-page login UI. |
manual | Shows an on-page login pill. Handy for static sites and local testing. |
cookie | Uses an existing first-party session cookie on the page’s origin. |
Runtime behavior
Section titled “Runtime behavior”- Graceful degradation. If
init()fails (e.g. the API is unreachable), the loader still binds and renders authored content — the page degrades to plain HTML, never a broken one. - Published content wins. On load, each editable element is hydrated with its published value; your authored HTML is the fallback shown until then.
- Visitors stay React-free. The editor chrome (
inlinecms-editor.js) loads only when an editor is in play (a session exists, ordata-access="manual"). - Shadow-isolated chrome. The editor UI mounts in a shadow root, so the host page’s CSS can’t bleed into the toolbar and dialogs (and vice versa).
See also
Section titled “See also”- Static HTML quick start
- React SDK reference — the component-based equivalent
- REST API — the HTTP API underneath