Section Creator — coding rules & what JavaScript is allowed
Understand exactly what HTML, CSS, and JavaScript you can use in the Section Creator — including how to write interactive components like menus, accordions, and animations correctly.
In this guide
- 1What is the Section Creator?
- 2HTML — what is supported
- 3CSS — what is supported
- 4JavaScript — what is allowed
- 5JavaScript — what is NOT allowed
- 6The most common block — inline onclick= (and how to fix it)
- 7Template tokens — dynamic content replaced when added to the builder
- 8The correct pattern — combining tokens with editable fields
- 9Editable attributes — quick reference
- 10Complete working example — animated reveal section
What is the Section Creator?
The Section Creator lets you write your own HTML and CSS to build completely custom sections — not limited to the builder's built-in templates. You can use any layout, style, or interactive feature you like, then save the section and add it to any of your websites.
Before saving, every section goes through an AI Security Check powered by Claude Haiku. This scan protects your visitors and the platform — but it is designed to allow all normal web development patterns. Only a small set of genuinely dangerous APIs are blocked.
HTML — what is supported
All standard HTML elements are supported:
h1–h6), paragraphs, lists, links, buttons, images, divs, sections, nav, header, footer, article, etc.<canvas> for animations and custom graphics<script> for interactive JavaScript (see rules below)Not allowed:
<iframe> — embeds external content<object> and <embed> — same risk as iframes<script src="..."> — loading external scripts from other servers<link rel="stylesheet" href="..."> — loading external CSS<base> — would redirect all relative URLs on the page<meta http-equiv="refresh"> — would redirect the visitorRoot element rule: Your section should have one root element (a <section>, <nav>, or <div>). Wrap everything inside it.
CSS — what is supported
All standard CSS is supported — layouts, animations, transitions, custom properties, media queries, pseudo-elements, gradients, filters, and more.
Always scope your styles with a unique class prefix:
```css
/* Good — scoped */
.my-hero { padding: 80px 24px; }
.my-hero h1 { font-size: 2rem; }
/* Bad — affects the whole page */
h1 { font-size: 2rem; }
body { background: red; }
`
Unscoped CSS will bleed into other sections and break your published site.
Avoid `position: fixed` on the root element without a scoping class — it can overlay the entire page. Using it inside a scoped class (for a sticky nav or modal overlay) is fine.
JavaScript — what is allowed
A <script> block inside your section HTML is fully supported for creating interactive components. The following APIs are all allowed:
DOM manipulation:
getElementById, querySelector, querySelectorAllclassList.add, classList.remove, classList.toggleinnerHTML, outerHTML, textContentcreateElement, appendChild, removeChild, setAttributestyle.property changes for animationsdocument.body.classList for scroll-lock and theme togglingEvents:
addEventListener, removeEventListenerclick, scroll, resize, keydown, mouseenter, focus, etc.Animations & scroll:
requestAnimationFrame, setTimeout, setIntervalIntersectionObserver — reveal-on-scroll effectsResizeObserver — responsive JavaScriptscrollIntoView, window.scrollTo, window.scrollYScreen / viewport:
window.innerWidth, window.innerHeightgetBoundingClientRectwindow.location.hash (reading the URL hash — useful for tab navigation)Other:
style.setPropertyMath, JSON.parse, JSON.stringifyJavaScript — what is NOT allowed
These APIs are blocked because they can be used to steal visitor data, send data off-site, or redirect visitors to phishing pages:
| Blocked | Reason |
|---|---|
| fetch(), XMLHttpRequest | Can send visitor data to external servers |
| document.cookie | Accesses session tokens |
| localStorage, sessionStorage | Persistent data access |
| eval(), new Function() | Executes arbitrary code strings |
| Dynamic import() | Loads external code at runtime |
| window.open() | Opens popups (phishing risk) |
| window.location =, location.href = | Redirects the visitor to another page |
| document.write() | Can inject scripts into the page |
| Inline onclick=, onload=, etc. | See the section below |
These restrictions only block actual data risk — they do not affect layout, animation, or UI interactivity in any meaningful way.
The most common block — inline onclick= (and how to fix it)
The most frequent security block is inline event handler attributes like onclick, onload, onmouseover, etc. These are always blocked regardless of what they contain.
Wrong — will be blocked:
```html
<button onclick="toggleMenu()">Menu</button>
<div onmouseover="this.style.color='red'">Hover me</div>
<img src="x" onerror="alert(1)">
`
Correct — use addEventListener in a script block:
```html
<nav id="my-nav">
<button id="my-toggle">Menu</button>
<ul id="my-menu">...</ul>
<script>
(function() {
var nav = document.getElementById('my-nav');
document.getElementById('my-toggle').addEventListener('click', function() {
nav.classList.toggle('open');
});
})();
</script>
</nav>
`
Wrap your script in an immediately-invoked function (function(){...})() to avoid global variable conflicts when your section appears alongside other sections on a page.
Why are inline handlers blocked? They are the original XSS attack vector — the browser executes whatever is in the attribute without any checks. A <script> block can be scanned for dangerous APIs; an onclick= attribute cannot.
Template tokens — dynamic content replaced when added to the builder
Use these tokens in your HTML to make your section automatically use real site data:
| Token | Replaced with |
|---|---|
| __BUSINESS_NAME__ | The site's business name |
| __BUSINESS_CITY__ | The business city |
| __LOGO_IMG__ | A complete <img> tag for the logo — NOT just a URL |
| __SITE_ID__ | The site ID (for API fetch URLs) |
| __BUSINESS_SLUG__ | URL-safe version of the business name |
Tokens are resolved the moment a user adds your section to a website in the builder — before they even see it in the Edit tab. In the Section Creator preview they show as placeholder values so you can check the layout.
Critical: `__LOGO_IMG__` is a complete img tag, not a URL. It expands to <img src="..." alt="..." style="height:32px...">. Place it directly inline in your HTML where the logo should appear — never as the src of another img element.
The correct pattern — combining tokens with editable fields
The most powerful technique is using tokens as the default text inside data-field elements, so that fields are both pre-filled with real business data AND fully editable in the builder.
Rule: put the token inside the element's text — never leave it empty.
```html
<!-- ✅ Correct — token is the element's initial text -->
<h1 data-field="headline">__BUSINESS_NAME__</h1>
<h2 data-field="tagline">Serving __BUSINESS_CITY__ since 2018</h2>
<!-- ❌ Wrong — empty element loses the token, field starts blank -->
<h1 data-field="headline"></h1>
`
When the section is added to a website, the builder reads each data-field element's text, resolves any tokens (__BUSINESS_NAME__ → "Sunrise Café"), then saves that as the field's starting value. The Edit tab shows the resolved text ready to customise.
The nav logo pattern — the canonical example:
```html
<a class="sc-nav__logo" href="#" data-href-field="logoLink">
__LOGO_IMG__<span data-field="logoText">__BUSINESS_NAME__</span>
</a>
`
__LOGO_IMG__ sits inline in the HTML before the span. The builder replaces it with the full logo img tag. No <img> element needed, no data-image attribute.__BUSINESS_NAME__ is the default text of the data-field span — resolved then made editable.data-href-field="logoLink" makes the logo link URL editable.`data-image` vs `__LOGO_IMG__` — never confuse these:
```html
<!-- ✅ data-image — for images the user will upload themselves -->
<img data-image="teamPhoto"
src="https://placehold.co/480x320/374151/9ca3af?text=Your+Photo"
alt="Team" />
<!-- ✅ __LOGO_IMG__ — for the site logo, placed inline with no img tag -->
__LOGO_IMG__
<!-- ❌ Wrong — __LOGO_IMG__ is not a URL, never put it in src -->
<img src="__LOGO_IMG__" alt="Logo" />
`
A data-image element always needs a real placeholder src URL — the image picker replaces it when the user uploads. __LOGO_IMG__ is a self-contained element that needs no wrapper.
Editable attributes — quick reference
Add these attributes to HTML elements so users can edit content in the builder's Edit tab:
| Attribute | What it does |
|---|---|
| data-field="key" | Makes text content editable. Always put initial text (or a token) as the element's content. |
| data-href-field="key" | Makes a link's href editable. Add to the same <a> as data-field for a fully-editable button. |
| data-image="key" | Makes an img src editable via an image picker. Always provide a placeholder src URL. |
| data-bg-color="key" | Makes a background colour editable. Shows a colour picker. |
Full example:
```html
<section class="sc-hero" data-bg-color="heroBg">
<h1 data-field="headline">__BUSINESS_NAME__</h1>
<p data-field="subtext">Your tagline here.</p>
<a data-field="buttonText" data-href-field="buttonLink" href="#">Get Started</a>
<img data-image="heroPhoto"
src="https://placehold.co/800x400/374151/9ca3af?text=Your+Photo"
alt="Hero" />
</section>
`
What each attribute produces in the Edit tab:
data-field="headline" → "Headline" text input, pre-filled with the resolved __BUSINESS_NAME__data-href-field="buttonLink" → "Button Link" URL field with page and anchor autocompletedata-image="heroPhoto" → image upload area (placeholder src shown until user uploads)data-bg-color="heroBg" → colour picker controlling the section backgroundComplete working example — animated reveal section
Here is a full section that uses IntersectionObserver for a scroll-reveal animation. It follows all the rules and will pass verification:
HTML:
```html
<section class="sc-reveal" id="sc-reveal-root">
<div class="sc-reveal__inner">
<h2 class="sc-reveal__title" data-field="headline">Why Choose Us</h2>
<div class="sc-reveal__grid">
<div class="sc-reveal__card">
<div class="sc-reveal__icon">⚡</div>
<h3 data-field="feat1Title">Fast</h3>
<p data-field="feat1Text">Results delivered on time, every time.</p>
</div>
<div class="sc-reveal__card">
<div class="sc-reveal__icon">🛡️</div>
<h3 data-field="feat2Title">Trusted</h3>
<p data-field="feat2Text">Hundreds of satisfied customers.</p>
</div>
<div class="sc-reveal__card">
<div class="sc-reveal__icon">❤️</div>
<h3 data-field="feat3Title">Supported</h3>
<p data-field="feat3Text">We're here whenever you need us.</p>
</div>
</div>
</div>
<script>
(function() {
var cards = document.querySelectorAll('#sc-reveal-root .sc-reveal__card');
var observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add('sc-reveal--visible');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.15 });
cards.forEach(function(card) { observer.observe(card); });
})();
</script>
</section>
`
CSS:
```css
.sc-reveal { background: #fff; padding: 80px 24px; }
.sc-reveal__inner { max-width: 960px; margin: 0 auto; text-align: center; }
.sc-reveal__title { font-size: 2rem; font-weight: 700; color: #111; margin-bottom: 48px; }
.sc-reveal__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 24px; }
.sc-reveal__card {
background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 12px; padding: 32px 24px;
opacity: 0; transform: translateY(24px); transition: opacity 0.5s, transform 0.5s;
}
.sc-reveal--visible { opacity: 1; transform: translateY(0); }
.sc-reveal__icon { font-size: 2rem; margin-bottom: 12px; }
.sc-reveal__card h3 { font-size: 1rem; font-weight: 600; color: #111; margin-bottom: 8px; }
.sc-reveal__card p { color: #6b7280; font-size: 0.9rem; line-height: 1.6; }
`
More in Builder
Builder layout and the top bar
Understand the full builder layout — the three panels, every top-bar button, the save system, and how to navigate pages.
Managing sections — add, reorder, duplicate, delete
Everything about sections: what they are, how to add them in the right position, reorder by dragging, duplicate, delete, and change their visual style.
Editing content — the Edit tab
How to edit text, buttons, links, colors, images, icons, and every other field in the content editor.
The AI Build & Edit drawer
How the AI chat works — generating new sections, redesigning existing ones, choosing models, using reference images, and understanding AI credits.
Media library, logo, fonts, and hero images
How to upload images and logos to the media library, set your site logo, choose fonts, and set a hero background image or video.
Power features — select mode, batch redesign, templates, shortcuts
Advanced builder techniques: select multiple sections for batch AI redesign, save custom section templates, use keyboard shortcuts, and apply full-site templates.
Managing pages in your website
How to add new pages, switch between pages, navigate internal links, and delete pages you no longer need.
Using templates smartly — get more with fewer AI credits
How to build a complete, professional website using ready-made templates without spending any AI credits — then use AI only where it matters most.
Empty Section — build any custom layout with AI or your own code
How to add a blank empty section to your page and use the AI drawer or Code Editor to turn it into any layout you can imagine — no templates, no limits.
Section Creator — build and save custom HTML/CSS sections
How to write your own HTML and CSS in the Section Creator, add editable fields with data attributes, run the AI security check, and reuse your sections across all your websites.
Creating new pages with AI — the complete guide
How to use the AI assistant to create full pages with sections and automatic nav wiring — including model choice, credit costs, and what to expect.
AI Assistant tips and tricks — get better results faster
Practical techniques for getting the most from the AI assistant — quick prompts, the right mode for the right job, how to save credits, and what the AI can actually do.
Save as My Template — reuse sections across all pages
How to save any section as a personal template and reuse it on any page or any website — the fastest way to keep your site consistent.