Skip to content

UI extension points

A compiled extension implements IUIExtension and returns a UIManifest. Contributions that reference React components or frontend handlers also need a frontend ESM bundle. Cove imports that bundle, registers functions from its default export’s components map, and combines the manifest with contributions from other enabled extensions.

This page describes the UI contributions Cove currently renders. The general extension-point catalog covers backend and provider capabilities.

Set JsBundle in extension.json when a contribution references a React component or frontend handler, and set CssBundle when custom styles are needed. Put the React components named by page, tab, slot, settings, and override contributions in the default export’s components map. Contribution ids and keys should be stable across releases because Cove uses them for registration, routing, preferences, and ordering.

Most contribution records contain:

  • ExtensionId, which must identify the owning extension
  • an exported ComponentName when the contribution renders React
  • Order, where lower values render earlier
  • a stable contribution-specific id or key

Extension components render inside an error boundary. They should still handle missing data, failed requests, and permission errors locally.

See Frontend runtime API for supported module imports, authenticated requests, and Cove’s public shared component barrel.

UIPageDefinition adds a top-level route.

FieldBehavior
RoutePage key used by Cove routing. Keep it unique and stable.
LabelNavigation and page label.
ComponentNameExported React component. Cove passes onNavigate; numeric detail-style routes also receive id.
ShowInNavAdds the page to the main navigation when true. Pages remain directly routable when it is false.
NavOrderPositions the navigation item.
IconOptional navigation icon. The currently recognized values are music and puzzle; other values render no icon.
RequiredPermissionRequires one permission before Cove shows or renders the page.
RequiredPermissions, RequiredPermissionModeRequires all listed permissions by default, or at least one when the mode is Any. A non-empty array takes precedence over RequiredPermission.

Unauthorized pages are omitted from extension navigation. Direct navigation renders Cove’s access-denied page instead of mounting the extension component. DetailRoute remains reserved and does not create a second route.

Page permission checks only control presentation. Protect every API used by the page with the matching server-side convention described in Extension permissions.

UISlotContribution inserts content at a host-published slot. Set ContentType to component with a ComponentName, or to html with Html. Multiple contributions to the same slot render in ascending Order.

The host passes a context object appropriate to the location. Detail slots receive the current entity and onNavigate; shared list slots receive the page key, title, filter state, filter callback, total count, and loading state. Treat context fields as location-specific rather than assuming every slot receives the same props.

PageSlot keys
Videovideo-detail-actions, video-detail-main-bottom
Performerperformer-detail-actions, performer-detail-bottom
Studiostudio-detail-actions, studio-detail-sidebar-bottom, studio-detail-bottom
Tagtag-detail-actions, tag-detail-sidebar-bottom, tag-detail-bottom
Gallerygallery-detail-actions, gallery-detail-main-bottom, gallery-detail-bottom
Imageimage-detail-actions, image-detail-sidebar-bottom, image-detail-main-bottom
Groupgroup-detail-actions, group-detail-sidebar-bottom, group-detail-main-bottom, group-detail-bottom
Slot keyLocation
list-page-toolbar-endEnd of every shared list-page toolbar.
<page-key>-list-toolbar-endEnd of a specific list page’s toolbar.
<page-key>-list-rowShared list-page row or grid extension region.
tag-card-footerFooter of a tag card.
performer-card-footerFooter of a performer card.
studio-card-footerFooter of a studio card.
video-card-contentBounded extension region within a video card.

Use only a slot key Cove publishes. An arbitrary name remains in the manifest but never renders.

UITabContribution adds a tab to supported detail pages. Cove currently consumes page types video, performer, studio, tag, gallery, and group.

FieldBehavior
KeyStable tab key. Cove prefixes it internally with ext:.
LabelVisible tab label.
PageTypeHost detail-page type receiving the tab.
ComponentNameExported component; receives entityId and onNavigate.
OrderInterleaves the tab with built-in tabs on performer, studio, tag, gallery, and group pages.
CountEndpointOn performer, studio, tag, gallery, and group pages, an optional endpoint template using {entityId}; return JSON containing count.
IconOptional icon name used by extension count-summary cards on performer, studio, and tag pages.
ManualContextsManual contexts active while the tab is selected.
RequiredPermissionRequires one permission before Cove returns the tab to a detail page.
RequiredPermissions, RequiredPermissionModeRequires all listed permissions by default, or at least one when the mode is Any. A non-empty array takes precedence over RequiredPermission.

Video renders contributed tabs after its built-in history tab and ignores Order, CountEndpoint, and Icon. The contract also names image and settings, but those page types do not currently mount contributed detail tabs. Use settings contributions for settings UI.

UISettingsTab creates a route under /settings/<key> in the Extensions settings group.

FieldBehavior
KeyStable route segment and tab key.
Label, DescriptionNavigation and page copy.
IconOptional icon name. Supported normalized values are database, download, filetext, folderopen, harddrive, history, info, keyboard, keyround, layers, monitor, playcircle, plug, scrolltext, search, searchcode, server, shield, upload, usercog, and users; unknown values fall back to plug.
ParentTabKeyNests the tab beneath another contributed settings tab.
SearchKeywords, AliasesMakes settings search and alternate URLs easier to discover.
LayoutPanels wraps contributions in cards; Page gives panels a full-width canvas.
OrderPositions the tab within the Extensions group.

UISettingsPanel supplies the rendered component. With no TargetTab, it appears on the built-in Extensions page. A panel can target a contributed settings-tab key or one of the explicitly mounted built-in keys: extensions, library, or ai-data. The only currently published built-in section target is TargetTab = "library" with TargetSection = "extensions"; other built-in route and section keys do not create mount points automatically. Panels receive no universal save contract; the component owns its data loading, validation, permissions, and mutations.

ExtensionAction adds executable UI actions. Contributions may come from UIManifest.Actions or IActionExtension.GetActions().

FieldBehavior
Id, LabelStable action identity and visible label.
ActionTypeUse toolbar for single-entity actions or bulk for selected list entities.
EntityTypesLimits the action to matching entity types; an empty array matches all.
PagesOptionally limits toolbar actions to matching page keys. Bulk action lookup does not apply this field.
ApiEndpointEndpoint Cove invokes with action, entity, page, and selected-id data.
HandlerNameExported frontend handler used instead of the endpoint when found.
RequiredPermissionHides the action when permission is absent.
SuppressSuccessAlertSkips Cove’s default queued-action success alert.
OrderSorts matching actions.

Toolbar rendering is currently available for video and image entity actions. Bulk actions render for selectable entity lists. context-menu is declared by the contract but has no frontend consumer yet.

UIListFilterContribution adds an advanced-filter row to the list matching EntityType.

  • Use FilterKey to target a filter key understood by that list’s backend request contract.
  • For extension-owned custom fields, set CustomFieldKey and CustomFieldType; Cove creates an extension-scoped filter key.
  • CriterionType controls the editor, with Modifiers, Options, and EntityReferenceType refining supported operations.
  • Order positions the filter among other extension contributions.

UIListSortContribution adds a sort choice for the matching entity type. Set either a backend-supported SortKey or a CustomFieldKey with its CustomFieldType. A visible sort option does not implement backend sorting by itself; the corresponding server-side list contract must understand the generated key.

UIThemeDefinition contributes a selectable theme. It can set CSS variables, load a theme stylesheet, select a component-style layer and layout-style layer, name a background animation, and declare a light or dark color scheme.

UIComponentStyleDef and UILayoutStyleDef add named appearance-layer choices. Their ids connect UI preferences to CSS behavior shipped by the extension; the records themselves only provide identity, labels, and descriptions.

Theme, component-style, and layout ids become stored user preferences. Keep them stable, and provide sensible behavior when a user retains an id after an extension is disabled.

UITutorialTopic contributes a topic to Cove Manual. Topics can be scoped by page and runtime context, nested with ParentTopicId, and ordered alongside built-in and other extension topics.

Each UITutorialSlide can contain a title, caption, bullet points, Markdown body, image, mock kind, and external links. Set Kind to setup when the topic is an installation or first-run guide that Cove should surface after install.

UIFeatureDefinition publishes a case-insensitive feature key and string options. Host UI code must explicitly look up that key; declaring one does not create visible UI on its own. Use a feature declaration when Cove already defines the integration key, and pair custom behavior with another visible contribution.

UIPageOverride replaces the component for an exact built-in page key. Cove chooses the highest Priority when multiple extensions target the same page, then renders the named component with onNavigate.

Prefer additive pages, tabs, and slots when possible. An override owns the whole page body and therefore couples more closely to routing and host expectations. The declared * target is not currently implemented and does not replace the application shell.

The public manifest also contains these declarations, but Cove does not currently render them:

  • UIPaneContribution
  • UIComponentOverride
  • UISelectorOverride
  • UIDialogOverride
  • UIPageDefinition.DetailRoute
  • UIPageOverride with target *
  • ExtensionAction with action type context-menu

Treat them as reserved contract surface, not working extension points. Shipping one today leaves the contribution unused rather than falling back to another location.

GoalPreferred contribution
Add a new workflowUIPageDefinition
Add a small element to an existing screenUISlotContribution
Add entity-specific detail contentUITabContribution
Add configuration UIUISettingsTab and UISettingsPanel
Run an operation from an entity or selectionExtensionAction
Extend list queryingUIListFilterContribution or UIListSortContribution
Add visual presetsUIThemeDefinition, UIComponentStyleDef, or UILayoutStyleDef
Add in-app helpUITutorialTopic
Advertise a host-known capabilityUIFeatureDefinition
Replace a built-in pageUIPageOverride, only when additive points cannot work

After choosing the contribution, see Frontend runtime API for supported imports, Packaging for the asset layout, and Permissions for access design.