Orchard Core Placement - Prompt Templates
Configure Orchard Core placement
You are an Orchard Core expert. Generate correct placement for shapes, editor shapes, tabs, cards, columns, and fluent display-driver locations.
Guidelines
placement.json is the standard way to place shapes in modules and themes.
- Display drivers can also place editor/display shapes with
.Location("...") or the fluent PlacementLocationBuilder.
- Placement can target a zone only, or a zone plus editor groupings such as tabs, cards, and columns.
- For Orchard Core editors that use tabs/cards/columns, the view must render Orchard's grouped output, typically with
@await DisplayAsync(Model.Content).
- Use tabs, cards, and columns only when Orchard Core is responsible for rendering the grouped editor UI.
- Column names are arbitrary labels used for CSS classes; they do not imply left/right behavior.
- Prefer neutral column names such as
Col, Main, Sidebar, or Details unless a name is intentionally tied to custom CSS.
- Use
- to hide a shape.
- Use
alternates to swap templates and wrappers to wrap a shape in additional markup.
- Use a custom
IShapePlacementProvider only when placement must be computed dynamically.
- Shape type and differentiator are calculated from the rendered shape, not from the content part or field name alone.
- Use
ContentPart_Edit to hide or move a whole content part editor row in the admin UI. Its differentiator is {ContentType}-{PartName}.
- Inner part editor shapes such as
BagPart_Edit, FlowPart_Edit, or TitlePart_Edit use {PartName} as differentiator and only affect the inner editor content, not the wrapper.
- Standard field shapes use
{PartName}-{FieldName} as differentiator.
- Field display-mode shapes use
{PartName}-{FieldName}-{FieldType}_Display__{DisplayMode} as differentiator.
- Always seal classes.
Placement string format
The placement format supports these segments:
Zone:position#TabName;tabPosition%CardName;cardPosition|ColumnName[_width][;columnPosition]
Every segment after Zone:position is optional.
Segment meanings
Zone - target zone such as Content, Header, Meta, Actions, or Parts
:position - position within the zone or within the current grouping
#TabName;tabPosition - editor tab name and the tab's ordering position
%CardName;cardPosition - editor card name and the card's ordering position
|ColumnName[_width][;columnPosition] - editor column name, optional Bootstrap width modifier, and optional column ordering position
Important ordering rules
- The separators must appear in this order when combined:
#, then %, then |.
- Use
; before the group position for tabs, cards, and columns.
- For columns, place the optional width after the name using
_, as in |Col_4;2 or |Sidebar_lg-3;2.
- Do not use
: after a tab, card, or column name. #General:1 creates the literal tab name General:1, which is wrong.
Valid examples
| Placement |
Meaning |
Content:5 |
Place the shape in the Content zone at position 5 |
Content:1#General;1 |
Place in the General tab |
Content:4%Interaction;1 |
Place in the Interaction card inside Content |
Content:4#Capabilities;8%Tools;3 |
Place in the Capabilities tab, then the Tools card |
| `Content:4#Capabilities;8%Tools;3 |
Col_4;2` |
Differentiator patterns
| Shape type |
Typical usage |
Differentiator pattern |
Example |
BagPart, FlowPart, TitlePart |
Part display shape or inner XxxPart_Edit shape from a part driver |
{PartName} |
Services, FlowPart, TitlePart |
ContentPart |
Display wrapper for parts without a dedicated display driver |
{PartName} |
GalleryPart |
ContentPart_Edit |
Whole content part editor row in admin |
{ContentType}-{PartName} |
PlacementTest-BagPart, LandingPage-Services, Article-TitlePart |
TextField, HtmlField, ContentPickerField, etc. |
Standard field display/editor shape |
{PartName}-{FieldName} |
Article-Subtitle, Address-City |
TextField_Display, HtmlField_Display, etc. |
Field display-mode shape |
{PartName}-{FieldName}-{FieldType}_Display__{DisplayMode} |
Blog-Subtitle-TextField_Display__Header |
PartName is the attached part name. For non-named parts it is usually the part type, such as BagPart, FlowPart, WidgetsListPart, or TitlePart. For named parts, use the custom name such as Services.
placement.json examples
Basic placement
{
"TextField_Edit": [
{
"place": "Content:2"
}
],
"MyPart_Edit": [
{
"place": "Content:5"
}
]
}
Cards inside the content editor
{
"AIProfileGeneralFields_Edit": [
{
"place": "Content:1%General;1"
}
],
"AIProfileDeployment_Edit": [
{
"place": "Content:2%Deployments;1"
}
],
"AIProfileInteractionFields_Edit": [
{
"place": "Content:3%Interactions;2"
}
]
}
Tabs and cards together
{
"MyTools_Edit": [
{
"place": "Content:7#Capabilities;8%Tools;3"
}
],
"MyAgents_Edit": [
{
"place": "Content:5#Capabilities;8%Agents;2"
}
]
}
Cards and columns together
{
"MyFieldA_Edit": [
{
"place": "Content:1%Layout;1|Col_4;1"
}
],
"MyFieldB_Edit": [
{
"place": "Content:1%Layout;1|Col_4;2"
}
],
"MyFieldC_Edit": [
{
"place": "Content:1%Layout;1|Col_4;3"
}
],
"MyLargeField_Edit": [
{
"place": "Content:2%Layout;1"
}
]
}
This places MyFieldA_Edit, MyFieldB_Edit, and MyFieldC_Edit in three separate col-md-4 wrappers on the same row, then renders MyLargeField_Edit full-width below the row in the same card.
Content type and display type filters
{
"MyPart": [
{
"contentType": ["BlogPost"],
"displayType": "Detail",
"place": "Content:5"
},
{
"contentType": ["Article"],
"displayType": "Summary",
"place": "Meta:2"
}
]
}
Differentiator, alternates, wrappers, and hide
{
"TextField": [
{
"differentiator": "BlogPost-Subtitle",
"place": "Content:2"
}
],
"MyShape": [
{
"alternates": ["MyShape__BlogPost"],
"wrappers": ["MyShape_Wrapper"],
"place": "Content:5"
}
],
"SecretShape": [
{
"place": "-"
}
]
}
Hiding whole part editor wrappers
{
"ContentPart_Edit": [
{
"differentiator": "PlacementTest-BagPart",
"place": "-"
},
{
"differentiator": "PlacementTest-FlowPart",
"place": "-"
},
{
"differentiator": "PlacementTest-WidgetsListPart",
"place": "-"
},
{
"differentiator": "PlacementTest-TitlePart",
"place": "-"
}
]
}
Use this pattern when you need to hide or move the whole editor row. Do not use BagPart_Edit, FlowPart_Edit, WidgetsListPart_Edit, or TitlePart_Edit for this unless you intentionally want to target only the inner editor shape.
Display driver placement
You can use either the string form or the fluent builder form.
String form
return Initialize<MyViewModel>("MyShape_Edit", model =>
{
model.Value = value;
})
.Location("Content:4%Interaction;1");
Fluent card placement
return Initialize<MyViewModel>("MyShape_Edit", model =>
{
model.Value = value;
})
.Location(c => c.Zone("Content", "4").Card("Interaction", "1"));
Fluent tab, card, and column placement
return Initialize<MyViewModel>("MyShape_Edit", model =>
{
model.Value = value;
})
.Location(c => c
.Zone("Content", "4")
.Tab("Capabilities", "8")
.Card("Tools", "3")
.Column("Col", "2", "4"));
This produces a col-md-4 column ordered second within the card.
Fluent layout zone placement
return Initialize<MyViewModel>("MyShape", model =>
{
model.Value = value;
})
.Location(c => c.Zone("Content", "5").AsLayoutZone());
Use .AsLayoutZone() when the placement should be treated as a layout zone rather than an editor grouping.
Custom placement provider
Use an IShapePlacementProvider when placement depends on runtime conditions.
using OrchardCore.DisplayManagement.Descriptors.ShapePlacementStrategy;
public sealed class MyPlacementProvider : IShapePlacementProvider
{
public Task<IPlacementInfoResolver> BuildPlacementInfoResolverAsync(IBuildShapeContext context)
{
return Task.FromResult<IPlacementInfoResolver>(new Resolver());
}
private sealed class Resolver : IPlacementInfoResolver
{
public PlacementInfo ResolvePlacement(ShapePlacementContext placementContext)
{
if (placementContext.ShapeType == "MyShape")
{
return new PlacementInfo
{
Location = "Content:5#General;1%Details;1",
};
}
return null;
}
}
}
Registering the provider
using OrchardCore.DisplayManagement.Descriptors.ShapePlacementStrategy;
public sealed class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IShapePlacementProvider, MyPlacementProvider>();
}
}
Orchard Core editor grouping guidance
- Use tabs when you need top-level editor sections.
- Use cards when you need visually grouped fields inside a zone or tab.
- Use columns when a card needs multi-column layout.
- Each shape with a column modifier gets its own column wrapper inside the row.
- Shapes without a column modifier render full-width outside the row, before or after the column row based on placement order.
- Use the column width modifier to control Bootstrap sizing, for example
_4 for col-md-4 or _lg-3 for col-lg-3.
- If the width is omitted, Orchard Core uses an equal-width Bootstrap column (
col-md).
- When placing display-driver editor shapes into cards, prefer keeping everything inside the
Content zone unless Orchard specifically expects another zone.
- In CrestApps-style editors, a card-only placement such as
Content:4%Interaction;1 is valid and preferred over inventing custom zones like Interaction:10.
Common zones
Content
Content:before
Content:after
Header
Navigation
Sidebar
Meta
Tags
Actions
Footer
1---2name: orchardcore-placement3description: Skill for configuring Orchard Core placement, including placement.json, tabs, cards, columns, alternates, wrappers, dynamic placement providers, and fluent location syntax in display drivers. Use this skill when requests mention Orchard Core Placement, Configure Orchard Core placement, Placement string format, Segment meanings, Important ordering rules, Valid examples, or closely related Orchard Core implementation, setup, extension, or troubleshooting work. Strong matches include work with PlacementLocationBuilder, IShapePlacementProvider, MyPart, TextField, MyShape, SecretShape, MyPlacementProvider, IPlacementInfoResolver, IBuildShapeContext, ShapePlacementContext, IServiceCollection, placement.json. It also helps with placement examples, Important ordering rules, Valid examples, placement.json examples, plus the code patterns, admin flows, recipe steps, and referenced examples captured in this skill.4license: Apache-2.05metadata:6 author: CrestApps Team7 version: "1.2"8---910# Orchard Core Placement - Prompt Templates1112## Configure Orchard Core placement1314You are an Orchard Core expert. Generate correct placement for shapes, editor shapes, tabs, cards, columns, and fluent display-driver locations.1516### Guidelines1718- `placement.json` is the standard way to place shapes in modules and themes.19- Display drivers can also place editor/display shapes with `.Location("...")` or the fluent `PlacementLocationBuilder`.20- Placement can target a zone only, or a zone plus editor groupings such as tabs, cards, and columns.21- For Orchard Core editors that use tabs/cards/columns, the view must render Orchard's grouped output, typically with `@await DisplayAsync(Model.Content)`.22- Use tabs, cards, and columns only when Orchard Core is responsible for rendering the grouped editor UI.23- Column names are arbitrary labels used for CSS classes; they do not imply left/right behavior.24- Prefer neutral column names such as `Col`, `Main`, `Sidebar`, or `Details` unless a name is intentionally tied to custom CSS.25- Use `-` to hide a shape.26- Use `alternates` to swap templates and `wrappers` to wrap a shape in additional markup.27- Use a custom `IShapePlacementProvider` only when placement must be computed dynamically.28- Shape type and differentiator are calculated from the rendered shape, not from the content part or field name alone.29- Use `ContentPart_Edit` to hide or move a whole content part editor row in the admin UI. Its differentiator is `{ContentType}-{PartName}`.30- Inner part editor shapes such as `BagPart_Edit`, `FlowPart_Edit`, or `TitlePart_Edit` use `{PartName}` as differentiator and only affect the inner editor content, not the wrapper.31- Standard field shapes use `{PartName}-{FieldName}` as differentiator.32- Field display-mode shapes use `{PartName}-{FieldName}-{FieldType}_Display__{DisplayMode}` as differentiator.33- Always seal classes.3435## Placement string format3637The placement format supports these segments:3839```text40Zone:position#TabName;tabPosition%CardName;cardPosition|ColumnName[_width][;columnPosition]41```4243Every segment after `Zone:position` is optional.4445### Segment meanings4647- `Zone` - target zone such as `Content`, `Header`, `Meta`, `Actions`, or `Parts`48- `:position` - position within the zone or within the current grouping49- `#TabName;tabPosition` - editor tab name and the tab's ordering position50- `%CardName;cardPosition` - editor card name and the card's ordering position51- `|ColumnName[_width][;columnPosition]` - editor column name, optional Bootstrap width modifier, and optional column ordering position5253### Important ordering rules5455- The separators must appear in this order when combined: `#`, then `%`, then `|`.56- Use `;` before the group position for tabs, cards, and columns.57- For columns, place the optional width after the name using `_`, as in `|Col_4;2` or `|Sidebar_lg-3;2`.58- Do not use `:` after a tab, card, or column name. `#General:1` creates the literal tab name `General:1`, which is wrong.5960### Valid examples6162| Placement | Meaning |63| --- | --- |64| `Content:5` | Place the shape in the `Content` zone at position 5 |65| `Content:1#General;1` | Place in the `General` tab |66| `Content:4%Interaction;1` | Place in the `Interaction` card inside `Content` |67| `Content:4#Capabilities;8%Tools;3` | Place in the `Capabilities` tab, then the `Tools` card |68| `Content:4#Capabilities;8%Tools;3|Col_4;2` | Place in a 4-wide column, ordered second, inside the `Tools` card inside the `Capabilities` tab |6970## Differentiator patterns7172| Shape type | Typical usage | Differentiator pattern | Example |73| --- | --- | --- | --- |74| `BagPart`, `FlowPart`, `TitlePart` | Part display shape or inner `XxxPart_Edit` shape from a part driver | `{PartName}` | `Services`, `FlowPart`, `TitlePart` |75| `ContentPart` | Display wrapper for parts without a dedicated display driver | `{PartName}` | `GalleryPart` |76| `ContentPart_Edit` | Whole content part editor row in admin | `{ContentType}-{PartName}` | `PlacementTest-BagPart`, `LandingPage-Services`, `Article-TitlePart` |77| `TextField`, `HtmlField`, `ContentPickerField`, etc. | Standard field display/editor shape | `{PartName}-{FieldName}` | `Article-Subtitle`, `Address-City` |78| `TextField_Display`, `HtmlField_Display`, etc. | Field display-mode shape | `{PartName}-{FieldName}-{FieldType}_Display__{DisplayMode}` | `Blog-Subtitle-TextField_Display__Header` |7980`PartName` is the attached part name. For non-named parts it is usually the part type, such as `BagPart`, `FlowPart`, `WidgetsListPart`, or `TitlePart`. For named parts, use the custom name such as `Services`.8182## placement.json examples8384### Basic placement8586```json87{88 "TextField_Edit": [89 {90 "place": "Content:2"91 }92 ],93 "MyPart_Edit": [94 {95 "place": "Content:5"96 }97 ]98}99```100101### Cards inside the content editor102103```json104{105 "AIProfileGeneralFields_Edit": [106 {107 "place": "Content:1%General;1"108 }109 ],110 "AIProfileDeployment_Edit": [111 {112 "place": "Content:2%Deployments;1"113 }114 ],115 "AIProfileInteractionFields_Edit": [116 {117 "place": "Content:3%Interactions;2"118 }119 ]120}121```122123### Tabs and cards together124125```json126{127 "MyTools_Edit": [128 {129 "place": "Content:7#Capabilities;8%Tools;3"130 }131 ],132 "MyAgents_Edit": [133 {134 "place": "Content:5#Capabilities;8%Agents;2"135 }136 ]137}138```139140### Cards and columns together141142```json143{144 "MyFieldA_Edit": [145 {146 "place": "Content:1%Layout;1|Col_4;1"147 }148 ],149 "MyFieldB_Edit": [150 {151 "place": "Content:1%Layout;1|Col_4;2"152 }153 ],154 "MyFieldC_Edit": [155 {156 "place": "Content:1%Layout;1|Col_4;3"157 }158 ],159 "MyLargeField_Edit": [160 {161 "place": "Content:2%Layout;1"162 }163 ]164}165```166167This places `MyFieldA_Edit`, `MyFieldB_Edit`, and `MyFieldC_Edit` in three separate `col-md-4` wrappers on the same row, then renders `MyLargeField_Edit` full-width below the row in the same card.168169### Content type and display type filters170171```json172{173 "MyPart": [174 {175 "contentType": ["BlogPost"],176 "displayType": "Detail",177 "place": "Content:5"178 },179 {180 "contentType": ["Article"],181 "displayType": "Summary",182 "place": "Meta:2"183 }184 ]185}186```187188### Differentiator, alternates, wrappers, and hide189190```json191{192 "TextField": [193 {194 "differentiator": "BlogPost-Subtitle",195 "place": "Content:2"196 }197 ],198 "MyShape": [199 {200 "alternates": ["MyShape__BlogPost"],201 "wrappers": ["MyShape_Wrapper"],202 "place": "Content:5"203 }204 ],205 "SecretShape": [206 {207 "place": "-"208 }209 ]210}211```212213### Hiding whole part editor wrappers214215```json216{217 "ContentPart_Edit": [218 {219 "differentiator": "PlacementTest-BagPart",220 "place": "-"221 },222 {223 "differentiator": "PlacementTest-FlowPart",224 "place": "-"225 },226 {227 "differentiator": "PlacementTest-WidgetsListPart",228 "place": "-"229 },230 {231 "differentiator": "PlacementTest-TitlePart",232 "place": "-"233 }234 ]235}236```237238Use this pattern when you need to hide or move the whole editor row. Do not use `BagPart_Edit`, `FlowPart_Edit`, `WidgetsListPart_Edit`, or `TitlePart_Edit` for this unless you intentionally want to target only the inner editor shape.239240## Display driver placement241242You can use either the string form or the fluent builder form.243244### String form245246```csharp247return Initialize<MyViewModel>("MyShape_Edit", model =>248{249 model.Value = value;250})251.Location("Content:4%Interaction;1");252```253254### Fluent card placement255256```csharp257return Initialize<MyViewModel>("MyShape_Edit", model =>258{259 model.Value = value;260})261.Location(c => c.Zone("Content", "4").Card("Interaction", "1"));262```263264### Fluent tab, card, and column placement265266```csharp267return Initialize<MyViewModel>("MyShape_Edit", model =>268{269 model.Value = value;270})271.Location(c => c272 .Zone("Content", "4")273 .Tab("Capabilities", "8")274 .Card("Tools", "3")275 .Column("Col", "2", "4"));276```277278This produces a `col-md-4` column ordered second within the card.279280### Fluent layout zone placement281282```csharp283return Initialize<MyViewModel>("MyShape", model =>284{285 model.Value = value;286})287.Location(c => c.Zone("Content", "5").AsLayoutZone());288```289290Use `.AsLayoutZone()` when the placement should be treated as a layout zone rather than an editor grouping.291292## Custom placement provider293294Use an `IShapePlacementProvider` when placement depends on runtime conditions.295296```csharp297using OrchardCore.DisplayManagement.Descriptors.ShapePlacementStrategy;298299public sealed class MyPlacementProvider : IShapePlacementProvider300{301 public Task<IPlacementInfoResolver> BuildPlacementInfoResolverAsync(IBuildShapeContext context)302 {303 return Task.FromResult<IPlacementInfoResolver>(new Resolver());304 }305306 private sealed class Resolver : IPlacementInfoResolver307 {308 public PlacementInfo ResolvePlacement(ShapePlacementContext placementContext)309 {310 if (placementContext.ShapeType == "MyShape")311 {312 return new PlacementInfo313 {314 Location = "Content:5#General;1%Details;1",315 };316 }317318 return null;319 }320 }321}322```323324### Registering the provider325326```csharp327using OrchardCore.DisplayManagement.Descriptors.ShapePlacementStrategy;328329public sealed class Startup : StartupBase330{331 public override void ConfigureServices(IServiceCollection services)332 {333 services.AddScoped<IShapePlacementProvider, MyPlacementProvider>();334 }335}336```337338## Orchard Core editor grouping guidance339340- Use tabs when you need top-level editor sections.341- Use cards when you need visually grouped fields inside a zone or tab.342- Use columns when a card needs multi-column layout.343- Each shape with a column modifier gets its own column wrapper inside the row.344- Shapes without a column modifier render full-width outside the row, before or after the column row based on placement order.345- Use the column width modifier to control Bootstrap sizing, for example `_4` for `col-md-4` or `_lg-3` for `col-lg-3`.346- If the width is omitted, Orchard Core uses an equal-width Bootstrap column (`col-md`).347- When placing display-driver editor shapes into cards, prefer keeping everything inside the `Content` zone unless Orchard specifically expects another zone.348- In CrestApps-style editors, a card-only placement such as `Content:4%Interaction;1` is valid and preferred over inventing custom zones like `Interaction:10`.349350## Common zones351352- `Content`353- `Content:before`354- `Content:after`355- `Header`356- `Navigation`357- `Sidebar`358- `Meta`359- `Tags`360- `Actions`361- `Footer`