Comment directives
Control the compiler with simple top-of-file comments.
Names are auto-derived from your component/function names. When you need to override the defaults, add a comment directive near the top of the file.
@cms-ignore
Skip a whole file/page — no regions are created for it.
// @cms-ignore
export default function Dashboard() { /* ... */ }@cms-readonly
Regions are still discovered (and visible in the editor) but can never be edited.
// @cms-readonly
export function LegalCopy() {
return <p>© 2026 Acme, Inc. All rights reserved.</p>;
}@cms-name(...)
Override the auto-derived display name for the page/file.
// @cms-name(Marketing Home)
export default function Page() { /* ... */ }@cms-locales(...)
Restrict the locale set for a file.
// @cms-locales(en,ar)
export function Hero() { /* ... */ }@cms-layout(...) (element — collections)
Place above a .map(...) to tell the runtime how to clone new items so bento /
alternating grids keep matching spans:
{/* @cms-layout(bento) */}
{FEATURES.map((f) => (
<Reveal key={f.title} className={f.span}>…</Reveal>
))}Values: bento · alternating · stack · grid.
bento / alternating cycle sibling templates (including md:col-span-* classes)
when you Add an item. Without the directive, arrays named like FEATURES also
auto-hint bento.
@cms-richtext / @cms-unite (element)
Place a JSX comment immediately above an element to treat it as one editable text field. Use this when a sentence is split across multiple nodes only for decoration (highlight, underline, motion wrappers, etc.).
export function Hero() {
return (
<>
{/* @cms-richtext */}
<p>
{start}
<Highlighter>{phrase}</Highlighter>
{end}
</p>
</>
);
}The compiler also auto-detects this pattern for known decorative wrappers
(Highlighter, RoughNotation, motion.span, name matches like *Highlight*,
…): headings and paragraphs that only contain text + those wrappers become a
single region without a directive. Native formatting (<strong>, <em>, …)
still becomes a richtext region as before.
@cms-unite is an alias of @cms-richtext.
@cms-section (element)
Native <section> and <article> elements are automatically discovered as
section regions — hideable page blocks in the editor (Hero, Features, CTA,
…). Use @cms-section when a page block uses a plain <div> (or similar) as
its root:
export function Promo() {
return (
<>
{/* @cms-section @cms-name(Promo band) */}
<div className="promo">
<h2>Ship faster</h2>
</div>
</>
);
}Sections are visibility-only (no value editor). Nested text/image/link fields remain editable when the section is shown.
Authoring mindset
Nexus is not pure drag-and-drop. The compiler discovers editable regions from your JSX; you still tell it what is marketing copy vs chrome:
- Decorative previews, hover followers, carousel chrome →
@cms-ignore - Prices/features from an API or product config →
@cms-readonlyor ignore - Sentences split only for highlights/motion →
@cms-richtext(or auto-unite) - Non-
<section>page blocks you want to hide →@cms-section
Run nexus doctor for reminders and a best-effort scan of motion-heavy files
missing @cms-ignore.
Edit mode and custom interactions
Comment directives control discovery (what becomes a CMS field). They cannot cancel React hover handlers (tilt, glimpse previews, custom cursors).
In edit mode Nexus freezes CSS/WAAPI/GSAP and hides [data-nexus-pointer-overlay].
For custom wrappers that still misbehave, use the package helpers:
import { useNexusEditMode } from "@nexus-cms/react";
export function LinkGlimpse({ children, ...props }) {
const editing = useNexusEditMode();
if (editing) return <a {...props}>{children}</a>;
return <FancyHoverPreview {...props}>{children}</FancyHoverPreview>;
}Also available: isNexusEditMode(), subscribeNexusEditMode(), and the
nexus:edit-freeze window event (detail.phase: "settle" | "release").
Mark decorative follower layers with data-nexus-pointer-overlay so freeze CSS
hides them automatically.
Handling UI changes
When the UI changes, re-run nexus generate (or keep nexus watch running).
Use nexus check to see drift:
npx nexus check --ciIt reports new regions to wire up, removed regions whose overrides are now orphaned, and changed regions — perfect for a CI gate.