DEVELOPER GUIDE

Your HTML. A little more human.

The markup API keeps client content separate from your code. Here's how to prepare a site for WireSwan.

Field detection is live · client editing is next
01

Let the words change.

Add data-edit to a text element. Your client can update its content while the surrounding layout stays yours.

Your code
<h1>
  Room to be.
</h1>
What your client gets

Room to be.

02

Give images a little freedom.

Mark an image with a stable key. Replacements will be re-encoded and resized before publishing.

Your code
<img
     src="/images/studio.webp"
     alt="A light-filled studio" />
What your client gets
Fixed — the owner cannot change this
03

A small palette. Plenty of personality.

Expose a handful of CSS variables. Keep the rest of your design system out of reach.

Your code
<style>
  :root { --primary: #ee633d; }
</style>
What your client gets
Fixed — only you can change this
04

One key. Every page.

Prefix a key with global: for shared content. Other keys belong to their page path. Keep keys stable so client edits can survive new releases.

Your code
<a
   href="tel:+40123456789">
  +40 123 456 789
</a>
What your client gets

+40 123 456 789

05

Ship a dark mode too.

Declare each colour twice in the same editable block — once plain, once with a -dark suffix — then map them in ordinary CSS. Your client sees both sets in their picker and can change either. The mapping itself stays yours, because which scheme applies is a decision, not a colour.

Your code
<style data-edit-colors>
  :root { --ink: #111; --paper: #faf8f3; }
</style>

<style>
  @media (prefers-color-scheme: dark) {
    :root { --ink: var(--ink-dark);
           --paper: var(--paper-dark); }
  }
</style>
What your client gets
AaAa
06

Hand over the search listing too.

A seo: key makes the page title and the meta description editable. Always per page, never rich text, and collapsed to a single line before publishing. You write the first version; your client can rewrite it when the business changes, instead of emailing you about it.

Your code
<title>Maison Ilie</title>

<meta name="description"
      data-edit="seo:description"
      content="A quiet salon in Cluj.">
What your client gets
maisonilie.roUntitled pageNo description, so a search engine invents one from the page.

That is the whole idea. The rest is reference.

Six attributes, and you have seen all of them work. Everything below is the detail you will want later and not now — every rule, limit and warning the uploader actually enforces, read from the code that enforces it.

  1. 01Every attributeAll six forms, in one table
  2. 02Naming a keyWhat makes a name valid, and what it belongs to
  3. 03Where it may goThe elements that accept it, and the markup that survives
  4. 04What a ZIP may holdSizes, counts and the file types we accept
  5. 05When it complainsAll eight warnings, and the fix for each
  6. 06What an owner cannot changeThe boundary, stated before you promise it
  7. 07Pictures they uploadLimits, and what we do to them
  8. 08Rules as textThe whole convention, to paste into your editor
  9. 09After it is upPreviews, republishing, rollback, domains

Every attribute, in one table

There are six things to know. This is all of them.

data-edit="hero-title"On a text element

The owner may rewrite the words. Bold, italic and links survive; the layout does not move.

data-edit="hero-image"On an <img>

The owner may replace the picture. We re-encode what they upload and serve it from the site's own address.

data-edit="global:phone"Anywhere, any page

One value shared by every page that uses the same key. Change it once, it changes everywhere.

data-edit="seo:title"On <title>

What search engines show as the headline. Kept to 60 characters.

data-edit="seo:description"On a <meta>

The sentence under the headline, written into content=. Kept to 155 characters.

data-edit-colorsOn a <style>

Every --custom-property inside becomes a colour the owner can pick. Up to 12.

data-edit-href="book-link"On an <a>

Where the link goes. The one way an owner can change a phone number in tel:, an address in mailto:, or a booking URL.

data-edit-alt="hero-alt"On an <img>

What the picture shows. For search engines, and for anyone who cannot see it.

data-edit-visible="holiday"On any element

The owner can switch the whole thing off. Switched off, it is removed from the page, not hidden with CSS.

Naming a key

A key is how the editor finds the same thing again after you republish. Keep it and the owner’s words come back; change it and they are orphaned.

  • Starts with a letter or a digit
  • Then letters, digits, - and _
  • Up to 64 characters
  • No spaces, dots or slashes

A plain key belongs to its page: hero-title on index.html and the same key on about.html are two separate things. Prefix it with global: to make them one.

Good

hero-titleopening-hoursglobal:phoneseo:description

Rejected

-titlehero titlehero.title

Where data-edit may go

On a picture, that is <img>. For words, one of these 31 elements — anything else is reported and left alone, because rewriting a tag we do not understand is how a layout gets broken.

aaddressbblockquotebuttoncaptioncitedddivdtemfigcaptionh1h2h3h4h5h6ilabellegendlipqsmallspanstrongsummarytdthtime

Inside one of them, an edit keeps <a>, <b>, <br>, <em>, <i>, <strong> and nothing else. If a heading contains an icon or a nested <span> you need to keep, mark the inner element instead of the heading.

What a ZIP may contain

  • At most 40 MB zipped, 120 MB unzipped
  • At most 600 files
  • An index.html at the root
  • No folder called _uploads — that name belongs to the owner’s own uploads

Static files only. There is no build step and nothing runs on the server, which is also why there is nothing on the server to keep patched.

Accepted file types

.avif.css.gif.htm.html.ico.jpeg.jpg.js.json.map.mjs.otf.png.svg.ttf.txt.wasm.webmanifest.webp.woff.woff2.xml

When the upload complains

None of these stop a site going up. Each one means one marked element was skipped, so the owner will not find it — which is worth a minute now rather than a message later.

Empty keydata-edit with nothing in it.

Give it a name, or remove the attribute.

Invalid keyThe name breaks the rule below.

Start with a letter or digit; letters, digits, - and _ after that; 64 characters at most.

Duplicate keyThe same key twice on one page.

Two elements that should always say the same thing want global:, not the same page key.

Type conflictOne key used on text in one place and an image in another.

A key is text or a picture, never both. Rename one.

Unsupported elementdata-edit on a tag we cannot safely rewrite.

Move it to one of the elements listed above, usually a span wrapped around the words.

Nested markupSomething inside the editable element we cannot keep.

Only <a>, <b>, <br>, <em>, <i>, <strong> survive an edit. Anything else belongs outside the marked element.

Invalid colourA property under data-edit-colors that is not a hex colour.

Use #rgb, #rrggbb or the same with alpha. Keep gradients and keywords in a property that is not marked.

Too many coloursMore than 12 properties under data-edit-colors.

Mark the ones the owner should choose; leave the derived shades to CSS.

Hand the rules to your editor

If you work with an assistant that reads instructions — Claude, Cursor, Copilot, whichever — paste this in once and it will mark a site correctly instead of guessing. It is the whole convention in one screen, so it reads just as well if you would rather keep it beside you.

Rules, as text
You are marking up a static website for WireSwan, which lets the site's owner edit
parts of it without touching the layout or the code. Follow these rules exactly.

MARK A PIECE OF TEXT
  Add data-edit="some-key" to the element holding the words.
  Allowed on: a, address, b, blockquote, button, caption, cite, dd, div, dt, em, figcaption, h1, h2, h3, h4, h5, h6, i, label, legend, li, p, q, small, span, strong, summary, td, th, time.
  Not allowed on anything else; move the attribute to a <span> around the words instead.
  Inside a marked element only <a>, <b>, <br>, <em>, <i>, <strong> survive an edit.
  If a heading contains an icon or a nested element you must keep, mark the inner element.

MARK AN IMAGE
  Add data-edit="some-key" to an <img>. Its src must be a root-relative path.

SHARE ONE VALUE ACROSS PAGES
  Prefix the key with global: — data-edit="global:phone". Same key, same value, every page.
  Without the prefix a key belongs to its page alone.

WHERE A LINK GOES
  Add data-edit-href="some-key" to an <a>, alongside its own href.
  This is the only way an owner can change a phone number in tel:, an address in mailto:,
  or a booking URL. Mark it whenever the link is something a business changes.
  Only http(s), mailto:, tel: and site-relative paths are accepted.

WHAT A PICTURE SHOWS
  Add data-edit-alt="some-key" to an <img>, alongside data-edit if they may replace it too.

A SECTION THEY CAN SWITCH OFF
  Add data-edit-visible="some-key" to any element. Switched off it is removed from the page,
  not hidden, so nothing is left for a search engine to find. Use it for anything seasonal:
  holiday hours, an offer, a notice.

SEARCH ENGINE FIELDS
  <title data-edit="seo:title"> and <meta name="description" data-edit="seo:description" content="...">.
  Keep the title under 60 characters and the description under 155.

COLOURS
  Put the colours in a <style data-edit-colors> block as custom properties:
    <style data-edit-colors> :root { --primary: #1a6fbf; } </style>
  Every property in that block becomes a colour the owner can pick. At most 12.
  Values must be hex (#rgb, #rrggbb, with or without alpha). Keep gradients and keywords
  in a style block that is not marked.
  For dark mode, define a second set of properties and let plain CSS choose between them.

KEY NAMES
  Start with a letter or digit, then letters, digits, - and _. Up to 64 characters.
  No spaces, dots or slashes. One key is text or an image, never both.
  Never reuse a key twice on one page; use global: when two places must agree.
  Keys are how an edit is found again after the site is republished, so keep them stable.

THE FILES
  Static only — no build step, nothing runs on the server. At most 600 files,
  120 MB unzipped. An index.html at the root.
  Allowed extensions: .avif .css .gif .htm .html .ico .jpeg .jpg .js .json .map .mjs .otf .png .svg .ttf .txt .wasm .webmanifest .webp .woff .woff2 .xml.
  Do not create a top-level folder called _uploads; that name is reserved.

WHAT TO MARK
  Everything the owner would reasonably want to change themselves: headings, body copy,
  prices, opening hours, phone numbers (the text AND the tel: href), addresses,
  photographs and their descriptions, the brand colours, and any section that is seasonal.
  Leave structure, navigation, scripts and layout unmarked — that is the point of the product.

What an owner cannot change

Worth knowing before you promise it. Everything here is deliberate — the product only works because the parts you did not mark cannot move.

Most attributesOnly href and alt

Editing replaces what is inside an element. Two attributes are the exception, and only because they are marked: data-edit-href and data-edit-alt. Classes, ids, styles, data attributes and everything else stay yours.

The page itselfNever

Layout, order, spacing, fonts, new sections, new pages. That boundary is the product: it is why you can hand a site over without being called when it breaks.

Anything unmarkedBy design

No attribute, no editing. An element you forgot is simply not offered — nothing warns the owner it is missing, so read your own pages once before you hand them over.

Hidden elementsCannot be reached

Text is edited by clicking it on the page. Something behind a tab, inside a closed menu or set todisplay: none cannot be clicked, so it cannot be edited. Colours and the search fields are different — those live in panels and are always reachable.

Pictures an owner uploads

Size12 MB each

Straight off a phone is fine. Larger is refused in the browser, before anything is sent.

How many200 per site

Counted across every page. Replacing a picture does not use another one.

What we do to itRe-encoded

Resized and converted by us, then served from the site’s own address under/_uploads/. Nothing an owner uploads is served as they sent it, which is also why a file that is not really an image cannot become one.

Your filesUntouched

Their uploads live beside your release, never inside it. Republishing cannot overwrite a picture they chose, and their picture cannot overwrite yours.

After it is up

Previews14 days

Free, marked as unpublished, and deleted when they run out. We email you before that happens.

RepublishingKeeps the owner’s words

Upload a new ZIP whenever you like. Every key that still exists keeps what the owner wrote; keys you removed are let go.

RollbackLast 10 versions

Every upload is kept whole, not as a patch. Going back is picking one and making it live again.

Editing in placeNo re-upload

Change a file from the dashboard and it becomes a new version, with the same history and the same way back.

Your sourceDownload any time

The live version with the owner’s edits already in it, as a ZIP, without our editing attributes. It is a site, not an export you have to convert.

Their domainTwo DNS records

WireSwan gets the certificate and renews it. Until then the site lives on a subdomain that works the same way.

DEVELOPER GUIDE

See it from your client side.

Explore the sample workspace