Skip to main content

Widgets

Widgets are the primary content blocks on MyDash dashboards. MyDash combines two widget sources:

  • Nextcloud Dashboard API widgets — every widget registered by an installed Nextcloud app, exposed via the v1 (IAPIWidget) or v2 (IAPIWidgetV2) interface, plus the legacy callback-based widgets.
  • Registry-driven custom widgets — a curated set of 17 in-app widget types defined in src/constants/widgetRegistry.js. Each entry pairs a Vue renderer with an Add Widget sub-form and a defaultContent shape.

This page documents the registry-driven catalog. For app-level Dashboard API widgets, see the host app's documentation.

Widget catalog

#TypeDisplay nameIconUse it for
1labelLabelFormatTitleShort, single-line headings inside a cell
2textTextFormatTextMulti-line markdown / HTML / table content
3imageImageCameraA single image (URL or Files-picker)
4linkLink ButtonLinkVariantOne-click action / external link button
5nc-widgetNextcloud WidgetViewDashboardProxy for any installed NC Dashboard widget
6headerHeader BannerViewHeadlineHero banner with overlay + CTA
7dividerDividerMinusVisual separator (line / heading / whitespace)
8filesFilesFolderInline Files browser (folder or file pin)
9peoplePeopleAccountGroupRoster of users with filters & birthdays
10quicklinksQuicklinksStarTile-grid of favourite links
11newsNewsRssBoxAggregated RSS / Atom feeds
12videoVideoVideoEmbedded video (URL or Files)
13calendarCalendarCalendarInternal NC calendars + external ICS
14linksLinksLinkBoxVariantSectioned link directory
15menuMenuViewDashboardDropdown / horizontal navigation menu
16containerContainerViewDashboardRecursive sub-grid host (max depth 3)
17tileTileViewGridSingle icon-tile shortcut

How widgets are persisted

Every placement is one row in oc_mydash_widget_placements:

ColumnStores
widget_idThe registry type key (e.g. label) — or a Nextcloud Dashboard widget id
grid_x / grid_y / grid_width / grid_heightGridStack position
style_configOptional per-placement style overrides (JSON)
contentPer-type configuration blob (JSON) — shape matches the type's defaultContent
custom_title / custom_iconPer-placement title/icon overrides
tile_*Legacy columns used by the standalone tile flow

The content column was added in Version001025Date20260508060000 to make the registry-driven types persistable end-to-end.

REST API

MethodEndpointDescription
GET/api/widgetsList Nextcloud Dashboard API widgets visible to the user
GET/api/widgets/itemsFetch items for one or more widgets
POST/api/dashboard/{dashboardId}/widgetsAdd a placement (accepts widgetId, grid coords, optional content)
PUT/api/widgets/{placementId}Update grid / style / content of a placement
DELETE/api/widgets/{placementId}Remove a placement

Known polish items

  • The wrapper still draws a "Widget" header above chrome-less types (label, divider, header). The data and rendering are correct; the title row is just visual noise on those three. Tracked as a follow-up.
  • The Add button can stay disabled when the widget type is freshly switched in the modal until the user touches a sub-form input — the validationTick watcher in AddWidgetModal.vue only bumps on update:content events, not on type changes. Workaround: edit any field once after switching type.

label

A short, single-line plain-text heading inside a dashboard cell. Content is rendered via Vue interpolation only (never v-html), so any HTML inside text is shown as literal characters — XSS-safe by construction.

Renderer: LabelWidget.vue · Form: LabelForm.vue · Spec: openspec/specs/label-widget/spec.md

FieldDefaultNotes
text''Heading text. Empty → renderer falls back to "Label".
fontSize16pxAny CSS length.
colorvar(--color-main-text)Empty = inherit theme.
backgroundColortransparentCell background.
fontWeightboldnormal / bold.
textAligncenterleft / center / right.

Add Widget — Label Label widget rendered


text

Multi-line text block with markdown / HTML / table rendering modes. New placements default to markdown; rows that pre-date contentMode fall through to the legacy HTML branch.

Renderer: TextDisplayWidget.vue · Form: TextDisplayForm.vue · Spec: openspec/specs/text-display-widget/spec.md

FieldDefaultNotes
text''Body. Markdown when contentMode='markdown'.
fontSize14px
color / backgroundColor'' / ''
textAlignleft
contentModemarkdownmarkdown / html.
tableMode / tableDatafalse / nullSwitches the renderer to a structured table.

Add Widget — Text Text widget rendered


image

A single image with three sources: external URL, uploaded file, or a Files-picker pin.

Renderer: ImageWidget.vue · Form: ImageForm.vue · Spec: openspec/specs/image-widget/spec.md

FieldDefaultNotes
url''External URL or Files path.
alt''Accessible alt text.
link''Optional click-through URL.
fitcovercover / contain / fill / none.

Add Widget — Image Image widget rendered


A single big call-to-action button. The displayMode='button' legacy mode draws one button; displayMode='list' toggles the alternate mode where links[] is rendered inline.

Renderer: LinkButtonWidget.vue · Form: LinkButtonForm.vue · Spec: openspec/specs/link-button-widget/spec.md

FieldDefaultNotes
label''Button text.
url''Destination.
icon''Material Design icon name.
actionTypeexternalexternal / internal.
backgroundColor / textColor'' / ''
displayModebuttonbutton / list.
listOrientation / listItemGapvertical / normalList-mode only.
links[][]List-mode children.

Add Widget — Link Button Link Button widget rendered


nc-widget

A proxy that mounts any Nextcloud Dashboard API widget inside a MyDash placement. Use it to drop the standard "Upcoming events", "Important mail", "Favorites", etc. widgets onto a MyDash dashboard.

Renderer: NcDashboardWidget.vue · Form: NcDashboardForm.vue · Spec: openspec/changes/nc-dashboard-widget-proxy/

FieldDefaultNotes
widgetId''Nextcloud Dashboard widget id (e.g. calendar, mail).
displayModeverticalvertical / horizontal.

Add Widget — Nextcloud Widget nc-widget rendered


A hero banner with optional background image, overlay, vertical/horizontal alignment, and a Call-to-Action button. The form's validate() requires a non-empty title, http(s) for any background URL, and CTA label/url paired (both or neither).

Renderer: HeaderWidget.vue · Form: HeaderForm.vue · Spec: openspec/specs/header-banner-widget/spec.md

FieldDefaultNotes
title''Required.
subtitle''
backgroundImageUrl''Must be http(s) if set.
backgroundImageFileIdnullFiles-picker source.
backgroundColor''
overlayModenonenone / solid / gradient.
overlayColor / overlayOpacity'' / 0.4
textColor''
textAlign / verticalAligncenter / middle
heightmediumsmall / medium / large.
ctanull{label, url, icon} or null.

Add Widget — Header Banner Header widget rendered


divider

A visual separator between sections. Three styles:

  • line — horizontal line with optional thickness/color/style
  • heading-break — line + heading text (heading is required for this style)
  • whitespace — pure spacing, no visible line

Renderer: DividerWidget.vue · Form: DividerForm.vue · Spec: openspec/specs/divider-widget/spec.md

FieldDefaultNotes
stylelineline / heading-break / whitespace.
lineColor / lineThickness / lineStyle'' / 1 / solid
whitespaceSizemediumsmall / medium / large.
headingText''Required for heading-break.

Add Widget — Divider Divider widget rendered


files

Inline Files browser pinned to a folder or single file. Supports search, sort, optional upload/delete, and a mime-type filter.

Renderer: FilesWidget.vue · Form: FilesForm.vue · Spec: openspec/specs/files-widget/spec.md

FieldDefaultNotes
folderPath''Absolute Files path. Empty = error placeholder.
fileIdnullPin a single file instead of a folder.
viewModelistlist / grid.
showThumbnailstrue
mimeTypeFilter[][]e.g. ['image/*'].
allowUpload / allowDeletefalse / false
sortBy / sortDescendingname / false

Add Widget — Files Files widget rendered


people

Roster of users with two selection modes (filter for rule-based, manual for hand-picked), per-field display toggles, and a birthday window.

Renderer: PeopleWidget.vue · Form: PeopleForm.vue · Spec: openspec/specs/people-widget/spec.md

FieldDefaultNotes
layoutgridgrid / list.
selectionModefilterfilter / manual.
selectedUsers[][]Manual mode.
filters[] / filterOperator[] / ANDFilter mode.
excludeDisabledtrue
showBirthdays / birthdayWindowDaystrue / 7
sortBy / columnsdisplayName / 3
showFields{displayName, role, organisation, email, phone, avatar, birthdate}All true by default.

Add Widget — People People widget rendered


A tile grid of favourite links — each with its own icon, label, and color. Useful for a "starter row" or as a compact navigation cluster.

Renderer: QuicklinksWidget.vue · Form: QuicklinksForm.vue · Spec: openspec/specs/quicklinks-widget/spec.md

FieldDefaultNotes
links[][]{id, label, url, icon, backgroundColor, textColor}.
iconSizemediumsmall / medium / large.
iconShaperoundedrounded / circle / square.
showLabels / labelPositiontrue / belowbelow / overlay / right.
columnsautoNumber or auto.
tileBackgroundStyletransparenttransparent / solid / outlined.
hoverEffectliftlift / fade / none.

Add Widget — Quicklinks Quicklinks widget rendered


news

Aggregated RSS / Atom feeds. The renderer fetches via the backend (/api/widgets/news/{placementId}/items) so CSP and CORS aren't issues.

Renderer: NewsWidget.vue · Form: NewsForm.vue · Spec: openspec/specs/news-widget/spec.md

FieldDefaultNotes
feedUrls[][]One or many RSS/Atom URLs.
layoutlistlist / cards.
itemLimit10
showThumbnailstrue
showSummary / summaryMaxCharstrue / 200
dateFormatrelativerelative / absolute.
metadataFilternullOptional regex / category filter.

Add Widget — News News widget rendered


video

Embedded video — either an external URL (mp4 / webm) or a Files-picker pin.

Renderer: VideoWidget.vue · Form: VideoForm.vue · Spec: openspec/specs/video-widget/spec.md

FieldDefaultNotes
sourceTypenullurl / file.
videoUrl''Used when sourceType='url'.
fileIdnullUsed when sourceType='file'.
autoplay / muted / loop / controlsfalse / true / false / true
aspectRatio16:916:9 / 4:3 / 1:1.
posterUrl''Optional thumbnail.

Add Widget — Video Video widget rendered


calendar

Agenda of upcoming events. Pulls from selected internal Nextcloud calendars and any number of external ICS feeds.

Renderer: CalendarWidget.vue · Form: CalendarForm.vue · Spec: openspec/specs/calendar-widget/spec.md

FieldDefaultNotes
internalCalendars[][]Calendar names from CalDAV.
externalIcsUrls[][]Public ICS URLs.
viewModeagendaagenda / month.
daysAhead14Look-ahead window.
colorByCalendartrue

Add Widget — Calendar Calendar widget rendered


A sectioned link directory — each section has a title and N links. Ideal for an intranet-style "useful links" panel.

Renderer: LinksWidget.vue · Form: LinksForm.vue · Spec: openspec/specs/links-widget/spec.md

FieldDefaultNotes
sections[][]{id, title, links: [{id, label, url, description, icon}]}.
columns3
linkLayoutcardcard / inline.
iconSizemedium
openInNewTabtrue
showSectionTitles / showLinkDescriptionstrue / true

Add Widget — Links Links widget rendered


A navigation menu — dropdown or always-expanded, horizontal or vertical.

Renderer: MenuWidget.vue · Form: MenuForm.vue · Spec: openspec/specs/menu-widget/spec.md

FieldDefaultNotes
items[][]{id, label, url, icon, children?}.
styledropdowndropdown / expanded.
orientationhorizontalhorizontal / vertical.
showIconstrue
expandedByDefaultfalse
activeItemHighlightunderlineunderline / background / none.

Add Widget — Menu Menu widget rendered


container

A recursive sub-grid host. Children live in content.placements[] and render through the inner GridStack instance bounded by the container's outer cell. Server-side REQ-CONT-006 caps recursion at 3 levels deep so a malformed payload can't blow up the renderer.

Renderer: ContainerWidget.vue · Form: ContainerForm.vue · Spec: openspec/specs/container-widget/spec.md

FieldDefaultNotes
placements[][]Child placements (recursive — same shape as a top-level placement).
backgroundColortransparent
paddingmediumnone / small / medium / large.
title''Optional section title.

Add Widget — Container Container widget rendered


tile

The registry-driven replacement for the deprecated standalone tile-creation flow. The renderer reads from BOTH the new inline content.{...} shape AND the legacy flat placement.tile* columns, so dashboards holding tile placements created via the deprecated oc_mydash_tiles flow keep rendering without a migration step.

Renderer: TileWidget.vue · Form: TileForm.vue · Spec: openspec/specs/tiles/spec.md

FieldDefaultNotes
title''Tile label.
icon''Material icon class or SVG path.
iconTypeclassclass / svg.
backgroundColor / textColor#3b82f6 / #ffffff
linkTypeappapp / external / internal.
linkValue''App id, URL, or internal route.

Add Widget — Tile Tile widget rendered