See your actual pages while you edit them.
Ripple Preview replaces the plain block entries in the Umbraco backoffice with the real thing: every block is rendered through your site's own views, stylesheets and scripts, then shown scaled to fit the editor. What editors see while writing is what visitors see after publishing.
- Real previews, not approximations. Blocks render server-side through the same Razor views
your frontend uses. Backgrounds, fonts, colors, columns and spacing all come out exactly as
they do on the live page — whatever CSS approach your site uses, including viewport-based
sizing (
vw/vh) and media queries, which resolve against a configurable design width. - Sections render whole. A block that contains other blocks renders as one piece, children included — so a dark section shows its white text on dark, side-by-side columns line up, and nested layouts at any depth look like the page.
- Scripts run. Carousels slide, animations play, embeds load.
- Everything stays editable. Click a block to open it. Hover over a section and the block under your cursor highlights — click to open exactly that block. A compact editing strip under each section handles adding, reordering, copying and deleting children, and the standard Umbraco action bar works as always.
- Editors stay in control. A toolbar on every block offers zoom (a large lightbox view), refresh, and an interact mode for trying carousels right in the preview. Structure mode outlines and names every block on the page when you want to see the layout skeleton. And one click (the eye icon in the top bar, or Ctrl+Shift+P) switches the whole backoffice back to the classic block cards at any time.
dotnet add package RipplePreview
Enable the editors you use in appsettings.json (the package ships IntelliSense for all options):
"RipplePreview": {
"DesignWidth": 1440,
"BlockGrid": {
"Enabled": true,
"Stylesheets": [ "/css/site.css" ],
"Scripts": [ "/js/site.js" ]
},
"BlockList": { "Enabled": true, "Stylesheets": [ "/css/site.css" ] }
}That's the whole setup: enable the editors, list the stylesheets and scripts your blocks need. Restart, and every block renders live.
Tips
- Using Umbraco's default Block Grid rendering? Add the generated layout stylesheet so nested
areas lay out correctly:
"Stylesheets": [ "/css/umbraco-blockgridlayout.css", ... ]. - Blocks implemented as ViewComponents (named after the element type alias) work without configuration and take precedence over partial views.
| Editor | Status |
|---|---|
| Block Grid (nested areas at any depth) | ✅ |
| Block List (including inside block workspaces) | ✅ |
| Rich Text Editor blocks | ✅ ("RichText": { "Enabled": true }) |
| Single Block | ✅ ("SingleBlock": { "Enabled": true }) |
Requires Umbraco 17.3+.
| Option | Description |
|---|---|
Enabled |
Turn previews on for this editor type (default false). |
ContentTypes |
Allowlist of element type aliases (empty = all). |
IgnoredContentTypes |
Denylist, applied when ContentTypes is empty. |
ViewLocations |
Extra view location templates searched before the defaults ({0} = alias). |
Stylesheets / Scripts |
Assets loaded into every preview. |
WrapperView |
Optional partial rendered around the block markup to replicate your grid chrome. Receives the block item as model, the inner markup via ViewData["rippleInnerHtml"], the width fraction via ViewData["rippleWidthFraction"], the owning page via ViewData["rippleOwner"] and ancestor blocks via ViewData["rippleAncestors"]. |
FullAreaPreviewContentTypes |
(Grid) element types that render the full preview without the child editing strip. |
StackedAreaPreviewContentTypes |
(Grid) element types whose own chrome previews separately, with children rendered as individual previews below. |
Default view conventions: /Views/Partials/blockgrid/Components/{alias}.cshtml,
/Views/Partials/blocklist/Components/{alias}.cshtml and
/Views/Partials/richtext/Components/{alias}.cshtml.
In views, ViewData["ripplePreview"] is true during preview rendering, and
Context.IsRipplePreview() is available via RipplePreview.Extensions.
ModelsBuilder is recommended but not required — without generated models, blocks render as
BlockGridItem<IPublishedElement>.
Most sites need nothing beyond Enabled and Stylesheets. Two situations need a little more:
If your templates lay out block grids through custom markup — your own container classes and column CSS instead of Umbraco's defaults — previews need that chrome too, or blocks will render unwrapped. Provide it once with a wrapper view:
"BlockGrid": { "WrapperView": "/Views/Partials/ripplePreview/gridWrapper.cshtml" }The wrapper receives the block as its model plus everything needed to reproduce your page chrome:
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockGridItem>
@using Umbraco.Cms.Core.Models.PublishedContent
@{
var inner = ViewData["rippleInnerHtml"] as Microsoft.AspNetCore.Html.HtmlString;
var fraction = ViewData["rippleWidthFraction"] is double f ? f : 1d; // block's share of the page width
var owner = ViewData["rippleOwner"] as IPublishedContent; // the page being edited
var nested = (ViewData["rippleAncestors"] as List<IPublishedElement>)?.Count > 0;
var width = fraction >= 0.999 ? "100vw"
: FormattableString.Invariant($"calc(100vw * {fraction:0.####})");
// Example: paint a per-page background, but only for top-level blocks —
// nested blocks sit on their parent's background instead.
var pageBackground = nested ? null : owner?.Value<string>("pageBackgroundColor");
}
@if (!string.IsNullOrEmpty(pageBackground))
{
<style>html.ripple-preview body { background: @pageBackground; }</style>
}
<style>
/* Repeat the grid classes your page template normally provides, so blocks —
and their children, which render inside this document too — lay out identically. */
.my-grid-container { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); }
.my-col-6 { grid-column: span 6; }
/* ... the rest of your column/row classes ... */
</style>
<div class="my-grid-container" style="width:@width">
@inner
</div>Rule of thumb: anything your page template contributes to how blocks look — grid classes, container widths, page backgrounds — belongs in the wrapper, because a block preview renders without the page template around it.
If a block's visual is produced by a script living in your page template (for example, a script that counts rows and generates numbered buttons), that script isn't part of the block's own markup, so the preview can't run it. Recreate just the visual part in a small script that loads only inside previews:
"BlockGrid": { "Scripts": [ "/js/my-preview-helpers.js" ] }// my-preview-helpers.js — loaded only inside Ripple previews
(function () {
function init() {
// recreate the page-level behavior your block relies on, e.g. generate
// the elements a template script would normally inject
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
else init();
})();Your live site is untouched — these scripts exist only in the preview documents.
| Mode | When | Behaviour |
|---|---|---|
| Full (default) | Most parents | The parent and all its children render as one piece, exactly like the frontend. A compact editing strip below the preview lists each child for editing and reordering. |
| Stacked | When children should preview individually | The parent's own markup previews on its own; children render as separate previews below. Opt in per type via StackedAreaPreviewContentTypes. |
| Solo | Read-mostly sections | Full preview without the editing strip; children are edited through their own workspaces. Opt in via FullAreaPreviewContentTypes. |
- "No view or ViewComponent found" shown in a block: the message lists every searched
location — add yours via
ViewLocations. - Preview looks unstyled: the preview only loads what you list in
Stylesheets(plus anything your views render inline). - A block renders blank: blocks driven by page-level scripts can't run those in isolation;
Ripple shows a labeled placeholder with the block's name and size instead. Add a small
preview-only script via
Scriptsif you want the real visual. - Sibling blocks don't stretch to equal height: row-level grid effects only apply between blocks rendered together. Children inside one section stretch correctly; separate top-level blocks render independently.
MIT — see LICENSE.md.
Parts of the server-side machinery that convert backoffice editor values into renderable models were adapted from Umbraco.Community.BlockPreview (MIT) — attribution details in NOTICE.md.