Skip to main content
Widgets are the core interactive components of Homarr boards. Each widget displays data from your services, provides controls, or shows useful information. With over 30 widget types available, you can build comprehensive dashboards for monitoring and managing your infrastructure.

Available Widget Types

Homarr includes widgets for various purposes:

App

Display application links with icons, descriptions, and status indicators. Supports ping monitoring and custom layouts.Integration: None required

Bookmarks

Organize multiple app links in a customizable list. Perfect for quick access to frequently used services.Integration: None required

iFrame

Embed external web pages directly in your dashboard. Useful for displaying existing monitoring pages.Integration: None required

Media Management Widgets

Media Server

Display library statistics from Plex, Jellyfin, or Emby. Shows total movies, TV shows, episodes, and music.Integration: Plex, Jellyfin, or Emby

Calendar

View upcoming releases for TV shows and movies from Sonarr, Radarr, Lidarr, or Readarr.Integration: Sonarr, Radarr, Lidarr, Readarr, or Home Assistant

Media Requests

View and manage media requests from Overseerr, Jellyseerr, or Seerr. Shows request statistics and recent requests.Integration: Overseerr, Jellyseerr, or Seerr

Media Releases

Display recently added media from your media servers. Shows new movies, TV episodes, and music.Integration: Plex, Jellyfin, or Emby

Media Transcoding

Monitor active transcoding sessions in Tdarr. Shows encoding progress and statistics.Integration: Tdarr

Download Management Widgets

Downloads

Monitor active downloads from torrent and usenet clients. Shows download progress, speeds, and queue.Integration: qBittorrent, Transmission, Deluge, SABnzbd, NZBGet, or Aria2

Indexer Manager

View indexer statistics and health from Prowlarr. Monitor indexer availability and usage.Integration: Prowlarr

System Monitoring Widgets

System Resources

Display CPU, memory, and storage usage from system monitoring tools.Integration: Dash., Glances, OpenMediaVault, Proxmox, TrueNAS, or Unraid

System Disks

Monitor disk usage and health across multiple drives.Integration: Dash., OpenMediaVault, TrueNAS, or Unraid

Docker Containers

View and control Docker containers. Shows container status and resource usage.Integration: None required (direct Docker socket access)

Health Monitoring

Display health metrics from infrastructure monitoring tools.Integration: Dash., Glances, OpenMediaVault, Proxmox, TrueNAS, Unraid, or Coolify

Network & Security Widgets

DNS Hole Summary

Display DNS filtering statistics from Pi-hole or AdGuard Home. Shows blocked queries and top domains.Integration: Pi-hole or AdGuard Home

DNS Hole Controls

Enable or disable DNS filtering with quick toggle controls.Integration: Pi-hole or AdGuard Home

Firewall

Monitor firewall statistics and rules from OPNsense.Integration: OPNsense

Network Controller

View Unifi Controller statistics including connected clients and network usage.Integration: Unifi Controller

Smart Home Widgets

Entity State

Display the state of Home Assistant entities (lights, sensors, switches).Integration: Home Assistant

Execute Automation

Trigger Home Assistant automations with a button click.Integration: Home Assistant

Utility Widgets

Clock

Display current time with customizable format and timezone support.Integration: None required

Weather

Show current weather conditions and forecast.Integration: None required (uses public API)

RSS Feed

Display recent items from RSS/Atom feeds.Integration: None required

Notebook

Add markdown notes and documentation to your board.Integration: None required

Stock Price

Track stock prices and market data.Integration: None required (uses public API)

Video

Embed video streams or video files.Integration: None required

Development Widgets

Releases

Monitor new releases from GitHub, GitLab, Docker Hub, NPM, and other sources.Integration: GitHub, GitLab, Docker Hub, NPM, Codeberg, LinuxServer.io, GitHub Container Registry, or Quay

Coolify

Monitor Coolify deployments and services.Integration: Coolify

Notifications

Display notifications from ntfy.Integration: ntfy

Gaming Widgets

Minecraft Server Status

Display Minecraft server status, player count, and MOTD.Integration: None required (direct server query)

Widget Configuration

All widgets share a common configuration structure with type-safe options:

Adding a Widget

  1. Enable Edit Mode on your board
  2. Click Add Widget
  3. Select a widget type from the gallery
  4. Configure widget options
  5. Click Add to place on the board
  6. Drag to position and resize as needed
  7. Click Save to persist changes

Widget Options

Each widget type has specific configuration options. Here’s an example of the App widget:
// From packages/widgets/src/app/index.ts:18
const createOptions = (settings) => ({
  // Select which app to display
  appId: factory.app(),
  
  // Open links in new tab
  openInNewTab: factory.switch({ defaultValue: true }),
  
  // Show app name
  showTitle: factory.switch({ defaultValue: true }),
  
  // Description display mode
  descriptionDisplayMode: factory.select({
    options: ["normal", "tooltip", "hidden"],
    defaultValue: "hidden"
  }),
  
  // Layout direction
  layout: factory.select({
    options: ["column", "column-reverse", "row", "row-reverse"],
    defaultValue: "column"
  }),
  
  // Enable status monitoring
  pingEnabled: factory.switch({ 
    defaultValue: settings.enableStatusByDefault 
  })
});

Option Types

Widgets use type-safe option builders:
Boolean toggle for on/off options:
factory.switch({ defaultValue: true })
Used for features like “Show Title”, “Open in New Tab”, etc.

Integration Requirements

Many widgets require integrations to function:

Checking Requirements

Widget definitions specify integration requirements:
// From packages/widgets/src/calendar/index.ts:34
export const definition = createWidgetDefinition("calendar", {
  icon: IconCalendar,
  supportedIntegrations: getIntegrationKindsByCategory("calendar"),
  integrationsRequired: false, // Optional: can work without integration
  createOptions() { /* ... */ }
});

Integration Categories

Widgets use integration categories to support multiple services:
  • calendar: Sonarr, Radarr, Lidarr, Readarr, Home Assistant, Nextcloud
  • mediaService: Plex, Jellyfin, Emby
  • downloadClient: qBittorrent, Transmission, Deluge, SABnzbd, NZBGet
  • dnsHole: Pi-hole, AdGuard Home
  • healthMonitoring: Dash., Glances, Proxmox, TrueNAS, Unraid
Some widgets work without integrations (like Clock, Weather, Notebook) while others require at least one integration to function properly.

Real-Time Updates

Widgets fetch data using React Query with automatic refetching:

Data Fetching

// Widgets use tRPC queries for real-time data
const { data, error, isLoading } = clientApi.widget.getData.useQuery({
  widgetId: itemId,
  integrationIds
});

Prefetching

Widgets can prefetch data for faster initial load:
// From widget prefetch pattern
export const prefetch: Prefetch<WidgetKind> = async (
  queryClient,
  items
) => {
  await Promise.all(
    items.map(async ({ options, integrationIds }) => {
      await queryClient.prefetchQuery({
        queryKey: ['widget', options, integrationIds],
        queryFn: () => fetchWidgetData(options, integrationIds)
      });
    })
  );
};

Refresh Intervals

Most widgets automatically refresh every 30-60 seconds. Some widgets support custom refresh intervals in their options.

Widget Lifecycle

Understanding how widgets load and update:
  1. Mount: Widget component loads with initial data
  2. Prefetch: Background data loading for faster display
  3. Render: Display data with loading states
  4. Update: Automatic refetch on intervals
  5. Edit: Update options in edit mode
  6. Unmount: Cleanup when removed or board changes

Widget Props

// From packages/widgets/src/definition.ts:66
interface WidgetComponentProps {
  // Widget configuration
  options: WidgetOptions;
  integrationIds: string[];
  itemId: string | undefined; // undefined in preview mode
  
  // Board context
  boardId: string | undefined; // undefined in preview mode
  isEditMode: boolean;
  
  // Option updates
  setOptions: ({ newOptions }) => void;
  
  // Dimensions
  width: number;
  height: number;
}

Custom Widget Options

Widgets can have complex nested configurations:

Sortable Lists

// From packages/widgets/src/bookmarks/index.tsx:27
items: factory.sortableItemList({
  ItemComponent: ({ item, handle: Handle, removeItem, rootAttributes }) => (
    <Group {...rootAttributes} justify="space-between">
      <Group>
        <Handle />
        <Avatar src={item.iconUrl} alt={item.name} />
        <Text>{item.name}</Text>
      </Group>
      <ActionIcon variant="transparent" color="red" onClick={removeItem}>
        <IconX size={20} />
      </ActionIcon>
    </Group>
  ),
  AddButton: CustomAddButton,
  uniqueIdentifier: (item) => item.id,
  useData: (initialIds) => {
    const { data } = clientApi.app.byIds.useQuery(initialIds);
    return { data };
  }
})

App Selection

Many widgets need to select apps or integrations:
// App selector input
appId: factory.app()

// Integration selector (automatic based on supportedIntegrations)
// Passed as integrationIds prop to widget

Error Handling

Widgets handle errors gracefully with custom error messages:
// From packages/widgets/src/app/index.ts:97
errors: {
  NOT_FOUND: {
    icon: IconDeviceDesktopX,
    message: (t) => t("widget.app.error.notFound.label"),
    hideLogsLink: true
  }
}
Error states display:
  • Custom icon and message
  • Optional link to server logs
  • Retry button
  • Fallback to generic error for unexpected issues

Widget Development

Creating custom widgets follows a defined pattern:
  1. Define the widget with type-safe options
  2. Create the component with data fetching
  3. Export with dynamic import for code splitting
// Widget definition pattern
export const { definition, componentLoader } = createWidgetDefinition(
  "widgetKind",
  {
    icon: IconComponent,
    supportedIntegrations: ["integration1", "integration2"],
    integrationsRequired: true,
    createOptions: (settings) => optionsBuilder.from(
      (factory) => ({
        // Define options here
      })
    )
  }
).withDynamicImport(() => import("./component"));

Best Practices

Performance

  • Use appropriate refresh intervals
  • Enable prefetching for frequently accessed widgets
  • Limit the number of real-time widgets per board
  • Test with actual data volumes

Configuration

  • Use descriptive widget names
  • Configure appropriate integrations
  • Set reasonable data limits (number of items to display)
  • Test widgets in both edit and view mode

Layout

  • Group related widgets together
  • Size widgets appropriately for their content
  • Leave space for expansion
  • Test responsive behavior on different screens

Integrations

  • Test connections before adding widgets
  • Use meaningful integration names
  • Document which widgets use which integrations
  • Monitor integration health

Next Steps

Set Up Integrations

Connect your services to enable widget functionality

Configure Boards

Learn how to organize widgets on boards

Select Icons

Customize widget and app icons

Search Features

Quickly access widgets and services

Build docs developers (and LLMs) love