You can treat Webflow’s DOM element as a mount point for small, reusable JS components and initialize them cleanly via Slater using element-scoped guards.
When to use this pattern
Markup (Designer)
<div data-dom="counter" data-start="0"> <span data-out></span> <button type="button">Increment</button></div>Component mounting helper (Slater)
function mountAll(selector, init) { document.querySelectorAll(selector).forEach((el) => {if (el.dataset._mounted) return; // prevent double initel.dataset._mounted = '1';init(el); });}function initCounter(el) {let n = parseInt(el.dataset.start || '0', 10);const out = el.querySelector('[data-out]');const btn = el.querySelector('button');const render = () => { if (out) out.textContent = String(n); };if (btn) btn.addEventListener('click', () => { n += 1; render(); });render();}// Mount all counters on the page immediately; safe if none existmountAll('[data-dom="counter"]', initCounter);Make it data‑driven
Working with libraries
function waitForGlobal(key, cb) {if (window[key]) return cb(window[key]);const id = setInterval(() => { if (window[key]) { clearInterval(id); cb(window[key]); } }, 50);}waitForGlobal('gsap', (gsap) => {mountAll('[data-dom="fancy-anim"]', (el) => {// use gsap safely here });});Evolving the pattern
Publishing flow
FAQ