Text Regions
A text region is any HTML element that editors can click to edit. You mark elements as editable by adding a data-cms-region or data-cms-global attribute.
Page-specific regions
Use data-cms-region for content that is unique to a single page:
<h1 data-cms-region="hero-title">Welcome to our site</h1>
<div data-cms-region="about-body">
<p>We build websites for small businesses.</p>
</div>
The attribute value is the region name — a string that identifies this region on this page. It can be anything you like, but should be descriptive. Region names must be unique within a page.
The initial content inside the element becomes the default content. Once an editor saves a change, the saved content is loaded from the database on every subsequent request.
Global regions
Use data-cms-global for content that should be the same on every page — things like a phone number in the footer, a company address, or a site-wide promotional banner:
<footer>
<p>Call us: <span data-cms-global="contact-phone">01234 567890</span></p>
<p data-cms-global="footer-address">123 High Street, London</p>
</footer>
When an editor saves a global region, the change applies everywhere that region name appears across the whole site. This is ideal for shared information that needs to stay consistent.
{cms:partial:slug}), it's automatically treated as global — even if you use data-cms-region. RuntCMS rewrites it to data-cms-global during partial processing.
Choosing the right container element
The region element is replaced by the editor's HTML when saved. Here are some guidelines:
Use div for multi-paragraph content
<div data-cms-region="about-text">
<p>First paragraph.</p>
<p>Second paragraph.</p>
</div>
Tiptap (the editor RuntCMS uses) wraps output in block elements. Using a <div> as the container works cleanly.
Avoid p as the outer container
Using <p> as the region container can cause issues because Tiptap outputs block elements (like another <p>) inside your <p>. Use <div>, <section>, or <span> depending on your needs.
Inline regions
For short inline text like a phone number or a tagline, use a <span>:
<span data-cms-global="tagline">Building better websites</span>
Region names
Region names are arbitrary strings. Follow these conventions:
- Use lowercase with hyphens:
hero-title,about-body - Be descriptive — the name shows up in the admin dashboard's recent edits list
- Names must be unique within a single page (but can repeat across different pages)
- Global region names must be unique across the whole site
Template tags inside region content
A small number of template tags work inside region and global region content. Most do not — tags like {cms:region}, {cms:global}, and {cms:image} are only processed in the page template file itself, not in saved region content. If you put them inside a region they will render as literal text.
Tags that do work inside region content:
{cms:login_link}— renders a login link for visitors, hidden when already logged in. Useful in a global footer region so it appears site-wide without adding it to every template.{cms:partial:slug}— partials are resolved before region content is output, so a partial reference inside a region will work. Useful for injecting shared snippets.
Tags that do not work inside region content:
{cms:system:runtbar}— should appear exactly once per page, just before</body>, in the template file. Placing it inside a region would inject duplicate toolbars on every page that region appears on.{cms:region},{cms:global},{cms:image},{cms:bg-image},{cms:page:*},{cms:seo:*}— these are template-level tags, resolved before the page is rendered. They are not re-processed inside saved content.
Default content
The HTML inside the region element is the default content — what's shown before any editor has saved a change. Once saved, the database content takes over and the default content is ignored.
Default content is shown to visitors too, so make sure it's real content rather than a placeholder.
HTML sanitization
When content is saved, RuntCMS sanitizes the HTML. The following tags are allowed:
p, br, strong, em, s, u, h2, h3, h4, ul, ol, li, a, img, blockquote, code, pre, table, thead, tbody, tr, th, td, div, span
Script and style tags are stripped entirely. On <a> tags, only href, target, and rel are allowed. JavaScript URLs (href="javascript:...") are blocked.
This protects against XSS even if an editor's session is compromised.
Example page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{cms:page:title} — Acme Co</title>
<meta name="description" content="{cms:page:description}">
{cms:site:favicon}
<link rel="stylesheet" href="{cms:site:path}/cms/css/site.css">
</head>
<body class="page-{cms:page:slug}">
<header>
<nav>{cms:nav:pages}</nav>
</header>
<section class="hero">
<h1 data-cms-region="hero-title">We make great things</h1>
<div data-cms-region="hero-copy">
<p>Acme makes world-class widgets. Order yours today.</p>
</div>
</section>
<footer>
<p data-cms-global="footer-contact">hello@acme.example</p>
<p>© 2025 Acme Co {cms:login_link}</p>
</footer>
{cms:system:runtbar}
</body>
</html>