orchardcore-widgets
Skill for creating and managing widgets in Orchard Core. Covers widget content types, zones, layers, layer rules, and widget placement configuration.
Files2
View on GitHubSKILL.mdsrc/CrestApps.AgentSkills/orchardcore/orchardcore-widgets/SKILL.md
GitHubOrchard Core Widgets - Prompt Templates
Create and Manage Widgets
You are an Orchard Core expert. Generate widget definitions, layer configurations, and zone placement for Orchard Core.
Guidelines
- Widgets are content types with the
Widgetstereotype. - Widgets are placed in zones defined by the theme layout.
- Layers control when widgets are visible using rule expressions.
- Enable
OrchardCore.WidgetsandOrchardCore.Layersfor widget support. - Each widget is a content item that can be edited from the admin panel.
- Layer rules are composed of conditions (URL, role, culture, homepage, authentication, content type, JavaScript, Boolean, All/Any groups); see
orchardcore-layersandorchardcore-rules. - Widgets that contain a
LiquidPart,LiquidField, orFacebookPluginPartcan only be edited or published by users withManageLiquidTemplates, and so can the pages that embed them in aFlowPart,BagPart, orWidgetsListPart. - HTML and Markdown in widgets are stored unsanitized; render the part or field shapes in widget templates rather than writing stored
Htmlwithraw. - Use
FlowPartto allow widgets inside content items. WidgetsListParteditor wrapper placement usesContentPart_Editwith differentiator{ContentType}-{PartName}.WidgetsListPartdoes not render its own front-end display shape; it injects widgets directly into layout zones.
Enabling Widget Features
{
"steps": [
{
"name": "Feature",
"enable": [
"OrchardCore.Widgets",
"OrchardCore.Layers",
"OrchardCore.Flows"
],
"disable": []
}
]
}
Creating a Widget Content Type
public sealed class Migrations : DataMigration
{
private readonly IContentDefinitionManager _contentDefinitionManager;
public Migrations(IContentDefinitionManager contentDefinitionManager)
{
_contentDefinitionManager = contentDefinitionManager;
}
public async Task<int> CreateAsync()
{
await _contentDefinitionManager.AlterTypeDefinitionAsync("{{WidgetName}}", type => type
.DisplayedAs("{{WidgetDisplayName}}")
.Stereotype("Widget")
.WithPart("{{WidgetName}}", part => part
.WithPosition("0")
)
);
await _contentDefinitionManager.AlterPartDefinitionAsync("{{WidgetName}}", part => part
.WithField("{{FieldName}}", field => field
.OfType("{{FieldType}}")
.WithDisplayName("{{FieldDisplayName}}")
.WithPosition("0")
)
);
return 1;
}
}
Layer Configuration via Recipe
{
"steps": [
{
"name": "Layers",
"Layers": [
{
"Name": "Always",
"LayerRule": {
"Conditions": [
{
"Name": "BooleanCondition",
"Value": true
}
]
},
"Description": "Widgets on this layer are always displayed."
},
{
"Name": "Homepage",
"LayerRule": {
"Conditions": [
{
"Name": "HomepageCondition",
"Value": true
}
]
},
"Description": "Widgets on this layer are displayed on the homepage."
},
{
"Name": "Authenticated",
"LayerRule": {
"Conditions": [
{
"Name": "IsAuthenticatedCondition",
"Value": true
}
]
},
"Description": "Widgets on this layer are displayed for authenticated users."
}
]
}
]
}
Layer Rule Expressions
Common layer rule conditions:
UrlCondition- Match by URL pattern (regex):^/$(homepage),^/blog/.*(blog section).IsAuthenticatedCondition- Visible for authenticated users.IsAnonymousCondition- Visible for anonymous users.RoleCondition- Visible for specific roles.CultureCondition- Visible for specific cultures.BooleanCondition- Always true/false.HomepageCondition- Visible when the request targets the homepage.JavascriptCondition- Custom JavaScript expression.
Placing Widgets in Zones
Widgets are assigned to zones and layers via the admin UI or recipes:
{
"steps": [
{
"name": "Content",
"data": [
{
"ContentItemId": "widget-hero-banner",
"ContentType": "HeroBanner",
"DisplayText": "Welcome Banner",
"Latest": true,
"Published": true,
"LayerMetadata": {
"Layer": "Homepage",
"Zone": "Header",
"Position": 0
},
"HeroBanner": {
"Heading": {
"Text": "Welcome to Our Site"
},
"Description": {
"Html": "<p>Your one-stop solution.</p>"
}
}
}
]
}
]
}
Widget Template (Liquid)
The Widget shape exposes Model.ContentItem, the Model.Content zone with
the shapes of its parts and fields, and Model.Header, Model.Meta,
Model.Footer, Model.Classes. Create Views/Widget-{{WidgetName}}.liquid
(Widget__{{WidgetName}}):
<div class="{{ Model.Classes | join: " " }}">
<h3>{{ Model.ContentItem.Content.{{WidgetName}}.Heading.Text }}</h3>
<div class="widget-body">
{{ Model.Content["{{WidgetName}}-Body"] | shape_render }}
</div>
</div>
Rendering the {PartName}-{FieldName} field shape processes shortcodes and
sanitizes the HTML. The built-in themes render Paragraph and RawHtml the
same way ({{ Model.Content.Paragraph-Content | shape_render }}).
Widget Template (Razor)
Create a template at Views/Widget-{{WidgetName}}.cshtml:
<div class="@string.Join(" ", Model.Classes)">
<h3>@Model.ContentItem.Content.{{WidgetName}}.Heading.Text</h3>
<div class="widget-body">
@await DisplayAsync(Model.Content.Named("{{WidgetName}}-Body"))
</div>
</div>
Widget Wrapper
Widgets rendered by Layers are wrapped by Widget_Wrapper
(Widget.Wrapper.cshtml) that adds the title container. Override it, or the
Widget-{{WidgetName}}.Wrapper / Widget-Zone-Footer.Wrapper alternates, to
remove the wrapper markup:
{{ Model.Content | shape_render }}
FlowPart for Inline Widgets
Allow widgets inside content items using FlowPart:
await _contentDefinitionManager.AlterTypeDefinitionAsync("Page", type => type
.WithPart("FlowPart")
);
FlowPart allows editors to add widgets inline within content item editing.
WidgetsListPart Editor Placement
To hide or move the whole WidgetsListPart editor row in the admin UI:
{
"ContentPart_Edit": [
{
"differentiator": "PlacementTest-WidgetsListPart",
"place": "-"
}
]
}
If the part is attached as a named part, replace WidgetsListPart with the part name.
Built-in Widget Content Types
The default recipes (Blog, Agency) create widget types such as:
Paragraph(anHtmlFieldnamedContent)RawHtml(anHtmlFieldnamedContent)BlockquoteMediaWidget/ImageContainer
Widget Best Practices
- Use the
Widgetstereotype for all widget content types. - Keep widget templates small and focused.
- Use layer rules to control visibility instead of conditional logic in templates.
- Test widgets across different zones and screen sizes.
- Use
FlowPartfor content-embedded widgets.