# Orchardcore Admin Dashboard

> Skill for creating admin dashboard widgets in Orchard Core. Covers the DashboardWidget stereotype, widget position and sizing, custom dashboard widget content types, widget template customization, and dashboard layout configuration. Use this skill when requests mention Orchard Core Admin Dashboard, Create and Configure Dashboard Widgets, Enabling Admin Dashboard, Widget Configuration Properties, Creating a Dashboard Widget Content Type via Recipe, Creating a Dashboard Widget Content Type via Migration, or closely related Orchard Core implementation, setup, extension, or troubleshooting work. Strong matches include work with OrchardCore.AdminDashboard, OrchardCore.ContentManagement.Metadata. It also helps with Creating a Dashboard Widget Content Type via Recipe, Creating a Dashboard Widget Content Type via Migration, Creating a Dashboard Widget Content Item via Recipe, plus the code patterns, admin flows, recipe steps, and referenced examples captured in this skill.

- Skill: `crestapps/orchardcore-admin-dashboard` (Agent Skill)
- Install (CLI): `npx skillmds@latest add crestapps/orchardcore-admin-dashboard`
- Raw SKILL.md: https://api.skillmd.com/api/skills/crestapps/orchardcore-admin-dashboard/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: CrestApps (https://skillmd.com/u/crestapps)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/crestapps/orchardcore-admin-dashboard

---


# Orchard Core Admin Dashboard - Prompt Templates

## Create and Configure Dashboard Widgets

You are an Orchard Core expert. Generate admin dashboard widgets, content types, and template configurations for Orchard Core.

### Guidelines

- Enable `OrchardCore.AdminDashboard` for admin dashboard widget support.
- Dashboard widgets are content items with the `DashboardWidget` stereotype.
- To create a widget content type, set its stereotype to `DashboardWidget`.
- `DashboardPart` is added automatically to every `DashboardWidget` type and stores `Position`, `Width`, and `Height`.
- Width and Height are unconstrained `double` grid-span values; the responsive dashboard layout determines how they render.
- `ManageAdminDashboard` permission is required to manage (add/edit/remove) widgets.
- `AccessAdminDashboard` permission is required for users without `ManageAdminDashboard` to view the dashboard.
- Users with only `AccessAdminDashboard` also need `ViewContent` or the applicable per-content-type view permission to see a widget.
- Customize widget appearance with templates named `DashboardWidget-{ContentType}.DetailAdmin.cshtml`.
- Always seal classes.

### Enabling Admin Dashboard

```json
{
  "steps": [
    {
      "name": "Feature",
      "enable": [
        "OrchardCore.AdminDashboard"
      ],
      "disable": []
    }
  ]
}
```

### Widget Configuration Properties

| Property | Type | Range | Description |
|----------|------|-------|-------------|
| `Position` | Numeric | Any | Controls the widget's order on the page. Lower values appear first. |
| `Width` | Double | Any | Grid-column span used by the responsive dashboard layout. The default is `1.0`; Orchard Core does not enforce a fixed range. |
| `Height` | Double | Any | Grid-row span used by the responsive dashboard layout. The default is `1.0`; Orchard Core does not enforce a fixed range. |

### Creating a Dashboard Widget Content Type via Recipe

```json
{
  "steps": [
    {
      "name": "ContentDefinition",
      "ContentTypes": [
        {
          "Name": "{{WidgetTypeName}}",
          "DisplayName": "{{WidgetDisplayName}}",
          "Settings": {
            "ContentTypeSettings": {
              "Stereotype": "DashboardWidget",
              "Creatable": false,
              "Listable": false,
              "Draftable": true
            }
          },
          "ContentTypePartDefinitionRecords": [
            {
              "PartName": "TitlePart",
              "Name": "TitlePart",
              "Settings": {
                "ContentTypePartSettings": {
                  "Position": "0"
                }
              }
            },
            {
              "PartName": "HtmlBodyPart",
              "Name": "HtmlBodyPart",
              "Settings": {
                "ContentTypePartSettings": {
                  "Position": "1"
                }
              }
            }
          ]
        }
      ]
    }
  ]
}
```

### Creating a Dashboard Widget Content Type via Migration

```csharp
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.Data.Migration;

namespace MyModule;

public sealed class DashboardMigrations : DataMigration
{
    private readonly IContentDefinitionManager _contentDefinitionManager;

    public DashboardMigrations(IContentDefinitionManager contentDefinitionManager)
    {
        _contentDefinitionManager = contentDefinitionManager;
    }

    public async Task<int> CreateAsync()
    {
        await _contentDefinitionManager.AlterTypeDefinitionAsync("{{WidgetTypeName}}", type => type
            .Stereotype("DashboardWidget")
            .DisplayedAs("{{WidgetDisplayName}}")
            .WithPart("TitlePart", part => part
                .WithPosition("0")
            )
            .WithPart("HtmlBodyPart", part => part
                .WithPosition("1")
            )
        );

        return 1;
    }
}
```

### Creating a Dashboard Widget Content Item via Recipe

```json
{
  "steps": [
    {
      "name": "Content",
      "data": [
        {
          "ContentItemId": "{{WidgetContentItemId}}",
          "ContentType": "{{WidgetTypeName}}",
          "DisplayText": "{{WidgetTitle}}",
          "Latest": true,
          "Published": true,
          "TitlePart": {
            "Title": "{{WidgetTitle}}"
          },
          "HtmlBodyPart": {
            "Html": "<p>{{WidgetContent}}</p>"
          }
        }
      ]
    }
  ]
}
```

### Custom Widget Template

Create a template named `DashboardWidget-{{ContentType}}.DetailAdmin.cshtml` where `{{ContentType}}` is the technical name of the content type:

```html
<div class="card h-100 @string.Join(' ', Model.Classes.ToArray())">
    @if (Model.Header != null || Model.Leading != null || Model.ActionsMenu != null)
    {
        <div class="card-header">
            @await DisplayAsync(Model.Leading)
            @await DisplayAsync(Model.Header)
            @if (Model.ActionsMenu != null)
            {
                <div class="btn-group float-end" title="@T["Actions"]">
                    <button type="button" class="btn btn-sm" data-bs-toggle="dropdown"
                            aria-haspopup="true" aria-expanded="false">
                        <i class="fa-solid fa-ellipsis-v" aria-hidden="true"></i>
                    </button>
                    <div class="actions-menu dropdown-menu">
                        @await DisplayAsync(Model.ActionsMenu)
                    </div>
                </div>
            }
        </div>
    }
    <div class="dashboard-body-container card-body p-2 h-100">
        @if (Model.Tags != null || Model.Meta != null)
        {
            <div class="dashboard-meta">
                @await DisplayAsync(Model.Meta)
                @await DisplayAsync(Model.Tags)
            </div>
        }
        @await DisplayAsync(Model.Content)
    </div>
    @if (Model.Footer != null)
    {
        <div class="card-footer">
            @await DisplayAsync(Model.Footer)
        </div>
    }
</div>
```

### Permissions

| Permission | Description |
|------------|-------------|
| `ManageAdminDashboard` | Add, edit, and remove dashboard widgets. Includes dashboard access. |
| `AccessAdminDashboard` | View the admin dashboard when the user does not manage it. |
| `ViewContent` | Required, with `AccessAdminDashboard`, unless a per-content-type view permission grants access. |

### Dashboard Widget with Custom Part via Migration

```csharp
using OrchardCore.ContentManagement.Metadata;
using OrchardCore.ContentManagement.Metadata.Settings;
using OrchardCore.Data.Migration;

namespace MyModule;

public sealed class StatsDashboardMigrations : DataMigration
{
    private readonly IContentDefinitionManager _contentDefinitionManager;

    public StatsDashboardMigrations(IContentDefinitionManager contentDefinitionManager)
    {
        _contentDefinitionManager = contentDefinitionManager;
    }

    public async Task<int> CreateAsync()
    {
        await _contentDefinitionManager.AlterPartDefinitionAsync("StatsWidgetPart", part => part
            .WithField("StatLabel", field => field
                .OfType("TextField")
                .WithDisplayName("Stat Label")
                .WithPosition("0")
            )
            .WithField("StatValue", field => field
                .OfType("NumericField")
                .WithDisplayName("Stat Value")
                .WithPosition("1")
            )
        );

        await _contentDefinitionManager.AlterTypeDefinitionAsync("StatsWidget", type => type
            .Stereotype("DashboardWidget")
            .DisplayedAs("Stats Widget")
            .WithPart("TitlePart", part => part.WithPosition("0"))
            .WithPart("StatsWidgetPart", part => part.WithPosition("1"))
        );

        return 1;
    }
}
```

### How to Add Widgets to the Dashboard

1. Log in with a user that has the `ManageAdminDashboard` permission.
2. Navigate to the admin dashboard (`/admin`).
3. Click the **Manage Dashboard** button.
4. Click **Add Widget** and select your dashboard widget content type.
5. Fill in the form, set Position, Width, and Height, then click **Publish**.

