Yoyo.Umbraco.LivePreview 0.0.4

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Yoyo.Umbraco.LivePreview --version 0.0.4
                    
NuGet\Install-Package Yoyo.Umbraco.LivePreview -Version 0.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Yoyo.Umbraco.LivePreview" Version="0.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Yoyo.Umbraco.LivePreview" Version="0.0.4" />
                    
Directory.Packages.props
<PackageReference Include="Yoyo.Umbraco.LivePreview" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Yoyo.Umbraco.LivePreview --version 0.0.4
                    
#r "nuget: Yoyo.Umbraco.LivePreview, 0.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Yoyo.Umbraco.LivePreview@0.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Yoyo.Umbraco.LivePreview&version=0.0.4
                    
Install as a Cake Addin
#tool nuget:?package=Yoyo.Umbraco.LivePreview&version=0.0.4
                    
Install as a Cake Tool

Yoyo Umbraco Live Preview

Downloads NuGet GitHub license

Yoyo Umbraco Live Preview adds an interactive preview workspace to Umbraco backoffice.

It renders your page inside an iframe, listens to in-progress editor values, posts them to a preview API endpoint, and returns updated HTML without saving/publishing.

To make regions editable in the preview, wrap markup with the <preview> tag helper. The package links each preview region to the correct property editor so editors can be focused, toggled, or updated directly from the preview overlay.

Features

  • Real-time page rendering without save or publish.
  • Overlay interaction from preview to property editors.
  • Supports primitive properties, pickers, media, rich text, block editors, and nested content structures.
  • Supports preview breakpoints (mobile/tablet/laptop/desktop/fill).
  • Supports strongly typed generated models and custom view models.

Compatibility

  • Umbraco 17
  • .NET 10

Install

Install from NuGet:

dotnet add package Yoyo.Umbraco.LivePreview

Register The Package

Register the package in your Umbraco builder pipeline.

Use AddLivePreview in your Umbraco builder chain.

builder.CreateUmbracoBuilder()
	.AddBackOffice()
	.AddWebsite()
	.AddComposers()
	.AddUmbracoFormsCustomProviders()
	.AddLivePreview()
	.SetContentLastChanceFinder<ContentLastChanceFinder>()
	.Build();

Add The Tag Helper

Add the tag helper import to your view imports file:

@addTagHelper *, Yoyo.Umbraco.LivePreview

Then use <preview> around markup you want to make interactive in live preview.

How The <preview> Tag Helper Works

The tag helper injects lightweight comment markers around your markup. The preview overlay script reads these markers and associates each region with a property payload.

The payload tracks:

  • document key
  • path within the editable data tree
  • editor alias
  • optional index
  • optional toggle behavior
  • optional empty-value state

This is why placement and binding style matter.

<preview> Attributes

  • for: model expression to bind a region to a property/object.
  • parent: optional parent context used for nested and alias-based resolution.
  • alias: explicit property alias lookup (commonly used for nested block content values).
  • index: explicit index for list/array item mapping.
  • toggle: toggles checkbox/radio/swatch-like editors instead of just focus.

Usage Patterns

1) Basic property binding

<preview for="@Model.TextBox">
	<div>@Model.TextBox</div>
</preview>

Use this for standard scalar properties.

2) Rich text and HTML content

<preview for="@Model.RichText">
	<div>@Model.RichText</div>
</preview>

3) Full object binding

<preview for="@Model">
	<div>...</div>
</preview>

Use this when the entire object has already been tracked and you want a single region tied to that object.

4) Explicit alias with parent (nested block/content scenarios)

<preview parent="@block.Content" alias="text">
	<div>@block.Content.Value("text")</div>
</preview>

Use this when you know the parent object and the exact property alias.

5) Collection item binding with explicit index

@{
	var index = 0;
}
@foreach (var item in Model.MultipleTextString)
{
	<preview for="@Model.MultipleTextString" index="@index">
		<li>@item</li>
	</preview>
	index++;
}

This is the safest pattern for primitive lists.

6) Toggle behavior (checkbox/radio/swatch style)

<preview for="@Model.Toggle" toggle="true">
	<div>@Model.Toggle</div>
</preview>

Use toggle="true" when click behavior should change value, not only focus the editor.

Why Primitive Collections Need Special Care

For primitive values (string/number/bool), many items can have equal values. Auto matching can become ambiguous when duplicates exist.

Recommended approach:

  • Always provide explicit index in loops for primitive collections.
  • Prefer binding to the parent collection with for="@Model.Property" plus index.
  • Do not rely on value-based matching when duplicate values are possible.

Good:

<preview for="@Model.Tags" index="@index">
	<span>@tag</span>
</preview>

Less reliable for duplicate primitive values:

<preview for="@tag">
	<span>@tag</span>
</preview>

Empty State Regions

If a property is empty, still render a preview wrapper so the editor can be opened from the preview:

<preview for="@Model.MultipleMedia">
	<div>None</div>
</preview>

This keeps the overlay discoverable even with no value.

Using Generated Models Vs Custom View Models

Generated models (ModelsBuilder)

No special mapping is usually required if your views already inherit generated models.

Custom view models (non-generated)

You must map document type aliases to view model factories using package options.

This allows live preview to resolve the same view model shape your site expects.

Example:

builder.CreateUmbracoBuilder()
	.AddBackOffice()
	.AddWebsite()
	.AddComposers()
	.AddUmbracoFormsCustomProviders()
	.AddLivePreview(options =>
	{
		// Factories that use Create(IPublishedContent, HttpRequest)
		options.MapViewModel("articleListingPage", (content, request, sp) =>
			sp.GetRequiredService<ArticleListingPageViewModelFactory>().Create(content, request));

		options.MapViewModel("articleCategoryPage", (content, request, sp) =>
			sp.GetRequiredService<ArticleListingPageViewModelFactory>().Create(content, request));

		options.MapViewModel("projectListingPage", (content, request, sp) =>
			sp.GetRequiredService<ProjectListingPageViewModelFactory>().Create(content, request));

		// Factories that only need IPublishedContent (no request)
		options.MapViewModel("articlePage", (content, sp) =>
			sp.GetRequiredService<ArticlePageViewModelFactory>().Create(content));

		options.MapViewModel("contactPage", (content, sp) =>
			sp.GetRequiredService<ContactPageViewModelFactory>().Create(content));

		options.MapViewModel("errorPage", (content, sp) =>
			sp.GetRequiredService<ErrorPageViewModelFactory>().Create(content));

		options.MapViewModel("projectPage", (content, sp) =>
			sp.GetRequiredService<ProjectPageViewModelFactory>().Create(content));

		// Generic PageViewModelFactory pattern
		options.MapViewModel("contentPage", (content, sp) =>
			sp.GetRequiredService<PageViewModelFactory>().Create<PageViewModel>(content));

		options.MapViewModel("homePage", (content, sp) =>
			sp.GetRequiredService<PageViewModelFactory>().Create<PageViewModel>(content));
	})
	.SetContentLastChanceFinder<ContentLastChanceFinder>()
	.Build();

Breakpoint Preview

The preview workspace includes built-in breakpoints:

  • Mobile
  • Tablet
  • Laptop
  • Desktop
  • Fill

Editors can switch breakpoints to validate responsive behavior while still editing content in place.

JavaScript And CSS Integration

The preview runtime exposes helpers and signals so front-end code can respond safely when preview HTML is re-rendered.

Razor / partial preview mode check

The package exposes an HttpContext extension method for server-side checks:

If Yoyo.LivePreview.Extensions is already imported in your _ViewImports.cshtml (or via global using), you can call this directly in partials without adding another @using.

@{
	var isPreviewMode = Context.IsPreviewMode();
}

@if (isPreviewMode)
{
	<div class="preview-only-hint">Preview mode</div>
}

Use this in partials or views when markup needs to differ between live preview rendering and normal front-end rendering.

window.previewMode

When a page is rendered inside live preview, the package sets:

window.previewMode = true;

Use this to branch behavior that should only run inside live preview.

if (window.previewMode) {
	// preview-specific behavior
}

Update lifecycle events

During DOM patching, the preview runtime emits custom bubbling events:

  • preview-before-updated: fired on each element before it is updated.
  • preview-updated: fired on each element after it is updated.

Example listeners:

document.addEventListener("preview-before-updated", (event) => {
	// cleanup or capture state before morphing
	const el = event.target;
});

document.addEventListener("preview-updated", (event) => {
	// re-bind behaviors after morphing
	const el = event.target;
});

Tip: if you initialize third-party UI widgets, re-run initialization logic from preview-updated.

window.previewService

The preview runtime exposes a global previewService for controlling how morph updates treat specific elements.

Available methods:

  • ignoreElement(el): prevent an element from being replaced/discarded.
  • unignoreElement(el): remove ignore behavior from that element.
  • preserveAttributes(el, attributes): keep selected attributes from the live element.
  • preserveClasses(el, classes): keep selected classes from the live element.
  • preserveStyles(el, styles): keep selected inline style properties from the live element.

Example:

const slider = document.querySelector(".my-slider");

if (slider && window.previewService) {
	window.previewService.ignoreElement(slider);
	window.previewService.preserveAttributes(slider, [
		"aria-expanded",
		"data-state",
	]);
	window.previewService.preserveClasses(slider, ["is-open", "is-active"]);
	window.previewService.preserveStyles(slider, ["transform", "height"]);
}

CSS: html.preview-mode

In preview rendering, the <html> element gets the preview-mode class.

Use it to scope preview-specific CSS:

html.preview-mode .cookie-banner {
	display: none;
}

html.preview-mode .debug-outline {
	opacity: 1;
}

Depending on breakpoint configuration, the runtime may also toggle hide-scrollbar on <html>.

Backoffice Breakpoint Customization

You can add, override, disable, or reorder breakpoints through your umbraco-package.json extension manifest.

Example:

{
	"$schema": "../../umbraco-package-schema.json",
	"name": "My Custom Preview Setup",
	"extensions": [
		{
			"type": "yoyo-preview-breakpoints",
			"alias": "yoyo.preview.breakpoints",
			"name": "Preview breakpoints",
			"meta": {
				"breakpoints": [
					{
						"id": "laptop",
						"label": "My laptop",
						"disabled": false
					}
				]
			}
		}
	]
}

How merge behavior works:

  • Matching id values override defaults.
  • New id values add custom breakpoints.
  • disabled: true hides a breakpoint.
  • weight controls sort order.

Default breakpoints

[
	{
		id: "mobile-portrait",
		label: "Mobile",
		minWidth: "360px",
		maxWidth: "375px",
		aspectRatio: "375 / 720",
		icon: "icon-mobile",
		scrollbar: false,
		weight: 10,
	},
	{
		id: "tablet-portrait",
		label: "Tablet",
		minWidth: "640px",
		maxWidth: "768px",
		aspectRatio: "768 / 1024",
		icon: "icon-ipad",
		scrollbar: false,
		weight: 20,
	},
	{
		id: "laptop",
		label: "Laptop",
		minWidth: "1024px",
		maxWidth: "1600px",
		aspectRatio: "16 / 9",
		icon: "icon-laptop",
		scrollbar: true,
		weight: 30,
	},
	{
		id: "desktop",
		label: "Desktop",
		minWidth: "1600px",
		maxWidth: "1920px",
		aspectRatio: "16 / 9",
		icon: "icon-display",
		scrollbar: true,
		weight: 40,
	},
	{
		id: "fill",
		label: "Fill",
		minWidth: "360px",
		maxWidth: "100%",
		height: "100%",
		aspectRatio: "auto",
		disablePadding: true,
		icon: "icon-fullscreen-alt",
		scrollbar: true,
		weight: 100,
	},
];

Breakpoint option reference

  • id (string, required): unique key. Matching ids override existing entries.
  • label (string): tab label shown in the preview UI.
  • minWidth (string): minimum viewport box width.
  • maxWidth (string): maximum viewport box width.
  • height (string): explicit viewport height (optional).
  • aspectRatio (string): CSS aspect-ratio value for the viewport.
  • icon (string): Umbraco backoffice icon name.
  • iconRotate (string): optional CSS rotate value for icon orientation.
  • disablePadding (boolean): removes preview container padding when true.
  • scrollbar (boolean): controls hide-scrollbar class behavior.
  • weight (number): lower values render earlier in the tab list.
  • disabled (boolean): hides the breakpoint when true.

Icon names come from standard Umbraco backoffice icons.

Troubleshooting

Preview does not appear

  • Ensure the document has a template.
  • Confirm the package is registered in the Umbraco builder pipeline.
  • Confirm App_Plugins assets are present.

Overlay appears but editor does not focus

  • Verify for/parent/alias mapping reflects actual property structure.
  • For collections, provide explicit index.
  • For nested blocks, prefer parent + alias when needed.

Wrong editor opens from list items

  • Add explicit index for primitive or repeating items.
  • Ensure loop index increments correctly.
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated