When you need more
Everything here is optional. The first half is advanced control over the save lifecycle itself; the second half is separate libraries you add with their own script tags.
Region reference
One attribute controls how any element takes part in saving. Keywords combine with spaces: clay="freeze no-undo".
| Keyword | Plain meaning | Typical use |
|---|---|---|
no-save | Lives on the page, never written to disk. Live sync leaves your copy alone. | Search boxes, connection badges, edit toolbars |
no-snapshot | Invisible to save and to sync. Every device keeps its own copy. | Per-device panel state |
freeze | Saved exactly as authored; runtime changes to its contents are ignored. | Clocks, tickers, computed summaries |
no-trigger-autosave | Saved normally, but edits here don't trigger an autosave. | High-churn text you'd rather batch |
no-watch | The mutation system ignores it entirely (implies no autosave trigger, no undo). | Third-party widgets that churn the DOM |
no-undo | Changes here aren't recorded in undo history. | Live regions where undo would feel wrong |
Live or computed text (clocks) → clay="freeze"
Third-party embeds → clay="no-watch"
Heavy editors, batch the saves → clay="no-trigger-autosave"
Advanced save attributes
“I want to clean an element up right before it's written to disk.”
Inline handlers that run on a copy of the element during the snapshot, so the live page never flickers. onbeforesave runs only for saves; onbeforesnapshot runs for every snapshot, including live-sync broadcasts.
<div onbeforesave="this.removeAttribute('data-temp')">…</div>
“Run something every time a save succeeds.”
<div onaftersave="console.log('saved at', event.detail.timestamp)">…</div>
“My stylesheet is generated on save; reload it without a flash.”
<link rel="stylesheet" href="style.css" refetch-on-save>
“Force one resource to re-download.”
Swaps a ?v= timestamp onto the element's href or src. Pairs well with onaftersave.
“I need JavaScript-level control over the outgoing HTML.”
Registers a callback that receives the cloned document right before serialization. Strip, rewrite, or annotate anything; the live page is untouched.
clay.beforeSave(doc => doc.querySelectorAll(".draft-marker").forEach(el => el.remove()));
Bring them in when the problem shows up
These aren't checkboxes; each is its own library with its own script tag and docs. They share clayjs's taste: HTML-first, no build step.
“I need a toast or a confirm dialog and don't want to build one.”
Ready-made toasts, modals, and ask/confirm/tell dialogs. It listens to clay:save-* events automatically, so adding it upgrades your save feedback for free. If you already have a toast library, keep yours: the events are public.
<script src="https://clayjs.com/clay-ui.js"></script>
“I want small behaviors without writing addEventListener boilerplate.”
onclickaway, onclickchildren, onrender, onmutation, onclone: HTML attributes for the events HTML forgot.
<script src="https://clayjs.com/clay-events.js"></script>
“Show or hide parts of the page based on a state attribute.”
Declarative show/hide: an ancestor sets option:view="kanban", descendants opt in or out with option: / option-not: attributes.
<script src="https://clayjs.com/clay-options.js"></script>
“closest() only searches up. I need the element near me.”
el.nearest(sel), el.val(), el.exec(), el.cycle(): small prototype helpers for DOM-first apps.
<script src="https://clayjs.com/clay-dom.js"></script>
“I miss jQuery's ergonomics, not its size.”
A chainable wrapper over querySelectorAll: All(".card").addClass("open").on("click", …). Zero dependencies, one file.
<script src="https://clayjs.com/all.js"></script>
“The small stuff: throttle, debounce, cookies, slugify.”
<script src="https://clayjs.com/clay-utils.js"></script>
“I want the morphing engine itself.”
The content-based DOM morphing that powers live sync ships inside the sync plugin and is exported as clay.morph. Use it to update a page in place while preserving focus, inputs, and animations.
“One MutationObserver for the whole page, with region rules applied.”
The shared mutation hub that autosave and live sync sit on. clay.Mutation.onAnyChange(opts, cb) respects clay="no-watch" regions so your observers and clayjs's agree about what counts as a change.