Contents

Cascade layers

This is the cascade-layer wrap on Maya's homepage hero — this widget, not the project. Composer and Preview wrap class definitions when a layer is set, so rounded-xl competes with host Tailwind the way she intends while she works. Publish to send that wrap with the published (and dev.) embed. A new widget starts as a snapshot of the project setting. Edits here stay on this widget.

What you can do

You already opened Maya's homepage hero from Widgets and put rounded-xl on it in Class Definitions. Those declaration blocks emit unlayered by default — a [data-rulecms-published-key] .rounded-xl rule with no @layer around it. Tailwind is layers: base, components, utilities. The same copied utility can steamroll her host pane or lose to it, depending on which stylesheet loads last.

Two everyday jobs:

  • Wrap this hero so copied utilities compete. Pick utilities here and the canvas follows. Edits stay on this widget. They do not write back to the project.
  • Pull a later project wrap onto this widget. When the template moves, Sync from Project copies that setting here. A wrap that exists only on this widget stays.

This setting wraps class definitions. It is not a second stylesheet, and it does not compile Tailwind. You still paste declaration blocks on Class Definitions — or you run Generate Tailwind CSS on a widget to compile the names it already uses. That flow writes into Class Definitions. It is not this page.

How wrapping thinks

Class names already travel. A column can carry rounded-xl today. Class Definitions say what that name means. Cascade layers says how those rules are emitted — unlayered, or wrapped in @layer utilities or @layer components. A class body cannot contain a top-level @layer. That is why this setting exists: the wrap has to sit outside the declaration list.

This setting belongs to this widget. A new widget starts as a snapshot of the project template. After that, edits here stay here. Composer and Preview wrap class definitions when a layer is set. Publish is how that wrap reaches the published (and dev.) embed.

Here is the case that surprises people. Maya copies rounded-xl from her Tailwind pane into Class Definitions. The hero looks right in Preview. On the live page the radius vanishes — or it steamrolls a later host utility — because the RuleCMS rule is unlayered and load order decides the fight. Wrapping in utilities puts that rule in the same layer Tailwind already uses, so the two copies compete the way Tailwind intends.

Composer and Preview read this widget's draft catalog. The published embed and the Development (dev.) draft GET read the published widget's catalog. Publish is how a draft catalog goes live.

A new widget starts as a copy of the project catalog. After that, edits here do not write back to the project. Later project edits do not come back here unless you click Sync from Project.

SurfaceWhat happens
Composer canvas and PreviewAlways inject from this widget's draft catalog when it is non-empty. The published-inclusion flag is ignored here so authors still see the result while they work.
Published widget (React SDK and HTML custom element)The widget fetch includes this widget's catalog when inclusion is on. Nested collections inherit. You do not get a copy per collection.

You need widget edit for this environment — the same permission as the composer — to change the wrap or click Sync from Project. Viewing CSS settings is a separate, lower permission. A viewer sees the setting and no edit button.

This does not compile Tailwind. You still paste declaration blocks on Class Definitions. Cascade layers only wraps that existing emit.

Wrap rounded-xl so it competes

You do this on the widget management page — the same place you open the composer. If the project already wraps in utilities, Sync is faster than picking it again. If only this hero should own the wrap, set it here.

  1. Open the organization → team → project → environment → Maya's homepage hero (or the Default Widget).
  2. Click CSS Settings. You land on Widget CSS Settings.
  3. On the Cascade layers card, click Edit Cascade layers (or View Cascade layers to scan first). The Sync from Project button also lives on this page and on the hub.
  4. To pull the project template: click Sync from Project. To set a wrap only this widget needs: open Edit, pick utilities under Wrap class definitions in, then Save Changes.
  5. On Staging or Production, publish when the live embed should carry the wrap. Development streams the draft — see Development Integration.

That is a safe stop. Composer already wraps rounded-xl when a layer is set. Publish is how visitors see it. Syncing updates the draft only — the live site does not move until she publishes again.

utilities or components

Edit is one select: Do not wrap (default), utilities, or components. There is no free-text layer name and no @layer reset, theme, utilities list. Saving Do not wrap deletes the setting.

You wantPick
Copied Tailwind utilities — rounded-xl, px-4, ring-parity-accent/30 — to compete with the host pane the way Tailwind utilities doutilities
Component-style classes that should sit under host utilitiescomponents
Today's unlayered emit, or a host that already layers these namesDo not wrap — or turn published inclusion off if the wrap should stay for Composer and Preview only
utilities vs components. Use utilities for copied Tailwind utilities. Use components when the classes should lose to host utilities. Unlayered rules win or lose by stylesheet order.

This widget's catalog

Open the widget, then CSS Settings, then Cascade layers. This catalog belongs to this widget.

To change the template for the next widget you create, edit the project catalog.

Class definitions on this widget can emit inside the layer you pick here.

  • Preview shows a short example using .rounded-xl — wrapped or unlayered — not a pasted stylesheet editor. That listing is for authors. It is not a second stylesheet RuleCMS compiles.
  • Edit is the select above. Help text changes as you pick: wrap in @layer utilities so they compete with host Tailwind utilities, wrap in @layer components so they sit with host component styles, or leave unlayered. Catalog Save is explicit.

A typical wrapped emit looks like this:

@layer utilities {
  [data-rulecms-published-key="env---w"] .rounded-xl {
    border-radius: var(--radius-xl);
  }
}

Empty or omitted is today's unlayered class emit. This setting never styles :root, html, or body. Variables, fonts, keyframes, themes, properties, and widget chrome are not wrapped. If there are no class definitions, nothing is emitted.

Sync from the project

Once this widget exists, its CSS settings are its own. The project catalog does not update them automatically. A Sync from Project button lives on this Cascade layers page — preview and edit — and on the widget's CSS Settings hub.

Syncing copies the project's version of an entry onto this widget. When both sides share an id, the project's value replaces the widget's. Entries that exist only on this widget are kept.

The button reads Synced with Project and is disabled when there is nothing to pull. Tiles on the CSS Settings hub show Project updates available when the project has updates for that type.

Syncing updates the draft. Publish the widget for live embeds to change. You can sync one type from this page or all nine from the hub.

Editing the project catalog never changes a widget by itself. A person must click Sync from Project.

Widgets are per-environment (Development, Staging, Production), but the project catalog is shared across all three. Syncing a Production widget pulls from the same project values a Development widget would.

There is no project-side action that pushes settings to many widgets. Syncing is always started from a widget — one type from its feature page, or all nine from the hub.

When the button is disabled

  • Unsaved edits — the helper reads Save or discard your changes before syncing. That stop exists so a later Save cannot overwrite what was just synced.
  • No project catalog — the helper reads This project has no CSS settings to sync.
  • Already in sync — the button itself reads Synced with Project and stays disabled.

Who can sync

Sync is governed by the widget edit permission for that environment — the same permission needed to change the widget in the composer. Viewing CSS settings is a separate, lower permission, and a viewer sees no button at all. Project CSS permission is not required: anyone who can edit the widget can pull project values onto it.

  • Missing permissionusers who can view CSS settings but cannot edit the widget in that environment do not see the button.

Turn off inclusion on published widgets

On this widget's Cascade layers page, the Published widgets accordion holds two radios. These radios control whether this widget's published and dev. embed carry the definitions. Composer and Preview still use this widget's catalog when inclusion is off. Changing a radio saves immediately. Catalog Save is separate.

The first radio is selected by default:

  • Wrap widget classes in this cascade layer when published widgets are rendered. A saved layer wraps the class stylesheet on the published (and dev.) embed. This is how RuleCMS makes Preview and the live embed match.
  • My apps already manage cascade layers. Do not wrap widget classes when the widget is being rendered. Published widgets still carry class definitions, but RuleCMS does not wrap them. Classes emit unlayered even if a layer is saved. Your host stylesheet already owns cascade.
Composer and Preview still wrap when inclusion is off. Authors keep seeing the wrap while they work. Only the published (and Development-draft) embed on your site emits classes unlayered. Class-definition inclusion is a separate toggle. An empty wrap plus the setting on is the same as off: there is nothing to wrap.
If you turn inclusion off, the host must already layer those utilities. Unlayered RuleCMS classes will fight the host pane by stylesheet order again. Check the published widget on a real route after you flip the setting.

How a published widget receives the setting

Hosts already fetch the widget once. When inclusion is on and a layer is set, RuleCMS hangs that name on the same response as a sibling of the widget and its class definitions — not folded into itemList, not copied onto each collection. The renderer needs the name next to the class sheet so it can wrap that existing emit, instead of inventing a second stylesheet.

{
  "success": true,
  "data": {
    "widget": { "publishedKey": "…", "itemList": "…", "…": "…" },
    "childCollections": { },
    "classDefinitions": {
      "rounded-xl": "border-radius: var(--radius-xl);"
    },
    "classLayer": "utilities"
  }
}

classLayer is omitted when the setting is empty, when inclusion is off, or if the catalog cannot be read. When inclusion is off, the same response also sends includeClassLayer: false so renderers that still receive a layer name must not wrap. Missing on the payload means include (legacy clients). The widget still loads. You never lose a page because a wrap is missing.

The React renderer (@rulecms/widget-react) and the HTML custom element (which bundles that renderer) wrap the existing class stylesheet, for example:

@layer utilities {
  [data-rulecms-published-key="env---w"] .rounded-xl {
    border-radius: var(--radius-xl);
  }
}

Nested collections inherit. Other widgets on the same page keep their own wrap. You do not get a copy per collection.

The Development draft fetch (Development Integration) reads the same fields from the draft widget row, so a dev. preview on your site matches composer.

Composer already wraps rounded-xl when a layer is set. Publish is how that draft wrap reaches the live embed. (Published traffic may sit in widget-cache for a short TTL — the same delay itemList already has.)

If the setting is empty, classes still emit — unlayered. Host utilities still work. Widgets that never used class definitions are unchanged.

React and the HTML embed wrap this pass. Other framework SDKs do not wrap class emit yet.

What to read next

This page is the story and the first walkthrough. The class catalog this setting wraps, the other catalogs, and the request your app already sends live on the pages below.

  • Class DefinitionsThe utility catalog this setting wraps. A class body cannot contain a top-level @layer; the wrap lives here.
  • CSS VariablesThe token catalog. Independent inclusion toggle. A class body can call var(--radius-xl); this wrap does not touch tokens.
  • Cascade layersThe project template for the next widget you create.
  • WidgetsCSS Settings on the widget management page: this wrap, Sync from Project, and Generate Tailwind.
  • Generate Tailwind CSSCompile the class names this widget already uses. That flow writes declaration blocks into Class Definitions. It does not replace this setting, and this setting does not compile Tailwind.
  • Fonts, Themes, CSS Properties, Keyframes, Position try, and Widget chromethe rest of the project templates on the same home. None of them are wrapped. Widget copies sit under Widgets in the sidebar.
  • Projects, Environments & TokensThe pipeline, and project CSS as the template for the next widget.
  • Development IntegrationPreview the live Development draft with a dev. token.
  • HTML Custom Element EmbedThe script tag that mounts a widget in light DOM so host utilities still reach it.
  • API ReferenceThe public widget GET, including classLayer.

How this fits

A widget is the content. Class definitions say what the class names on that widget mean. Cascade layers wraps those rules so they compete with Maya's Tailwind pane instead of steamrolling it. It does not replace the widget, and it does not compile Tailwind. The Composer is where a column stores the name.

This catalog belongs to this widget. Copy and promote copy these columns as-is. The project catalog is only the starting snapshot. Use Sync from Project on this page or the CSS Settings hub to pull later project updates.

  • This is not “compile Tailwind inside RuleCMS.” You paste declaration blocks you already have — or you run Generate Tailwind CSS on this widget to compile the names it already uses. That generator writes into Class Definitions. It is not this page.
  • Leave the setting empty if unlayered emit is what you want. Class names still work. Nothing extra is sent to the published page.
  • This is not generic @layer authoring. You cannot name a layer reset or write a layer-order list. At most one wrap, allowlisted names only.
  • Ask whoever owns the stylesheet which layer those names already live in. Wrapping a host utility a second time in a different layer is how copied classes start fighting again.