Files
yusing 4ec352f1f6 refactor(homepage/icon): check service health before fetching icons and add retry logic
The icon fetching logic now checks if the target service is healthy before
attempting to fetch icons. If the health monitor reports an unhealthy status,
the function returns HTTP 503 Service Unavailable instead of proceeding.

Additionally, the icon cache lookup now includes infinite retry logic with a
15-second backoff interval, improving resilience during transient service
outages. Previously, failed lookups would not be retried.

The `route` interface was extended with a `HealthMonitor()` method to support
the health check functionality.
2026-01-09 21:48:35 +08:00
..

Homepage

The homepage package provides the GoDoxy WebUI dashboard with support for categories, favorites, widgets, and dynamic item configuration.

Overview

The homepage package implements the WebUI dashboard, managing homepage items, categories, sorting methods, and widget integration for monitoring container status and providing interactive features.

Key Features

  • Dynamic homepage item management
  • Category-based organization (All, Favorites, Hidden, Others)
  • Multiple sort methods (clicks, alphabetical, custom)
  • Widget support for live data display
  • Icon URL handling with favicon integration
  • Item override configuration
  • Click tracking and statistics

Architecture

graph TD
    A[HomepageMap] --> B{Category Management}
    B --> C[All]
    B --> D[Favorites]
    B --> E[Hidden]
    B --> F[Others]

    G[Item] --> H[ItemConfig]
    H --> I[Widget Config]
    H --> J[Icon]
    H --> K[Category]

    L[Widgets] --> M[HTTP Widget]
    N[Sorting] --> O[Clicks]
    N --> P[Alphabetical]
    N --> Q[Custom]

Core Types

Homepage Structure

type HomepageMap struct {
    ordered.Map[string, *Category]
}

type Homepage []*Category

type Category struct {
    Items []*Item
    Name  string
}

type Item struct {
    ItemConfig
    SortOrder    int
    FavSortOrder int
    AllSortOrder int
    Clicks       int
    Widgets      []Widget
    Alias        string
    Provider     string
    OriginURL    string
    ContainerID  string
}

type ItemConfig struct {
    Show           bool
    Name           string
    Icon           *IconURL
    Category       string
    Description    string
    URL            string
    Favorite       bool
    WidgetConfig   *widgets.Config
}

Sort Methods

const (
    SortMethodClicks       = "clicks"
    SortMethodAlphabetical = "alphabetical"
    SortMethodCustom       = "custom"
)

Categories

const (
    CategoryAll       = "All"
    CategoryFavorites = "Favorites"
    CategoryHidden    = "Hidden"
    CategoryOthers    = "Others"
)

Public API

Creation

// NewHomepageMap creates a new homepage map with default categories.
func NewHomepageMap(total int) *HomepageMap

Item Management

// Add adds an item to appropriate categories.
func (c *HomepageMap) Add(item *Item)

// GetOverride returns the override configuration for an item.
func (cfg Item) GetOverride() Item

Sorting

// Sort sorts a category by the specified method.
func (c *Category) Sort(method SortMethod)

Usage

Creating a Homepage Map

homepageMap := homepage.NewHomepageMap(100) // Reserve space for 100 items

Adding Items

item := &homepage.Item{
    Alias:       "my-app",
    Provider:    "docker",
    OriginURL:   "http://myapp.local",
    ItemConfig: homepage.ItemConfig{
        Name:        "My Application",
        Show:        true,
        Favorite:    true,
        Category:    "Docker",
        Description: "My Docker application",
    },
}

homepageMap.Add(item)

Sorting Categories

allCategory := homepageMap.Get(homepage.CategoryAll)
if allCategory != nil {
    allCategory.Sort(homepage.SortMethodClicks)
}

Filtering by Category

favorites := homepageMap.Get(homepage.CategoryFavorites)
for _, item := range favorites.Items {
    fmt.Printf("Favorite: %s\n", item.Name)
}

Widgets

The homepage supports widgets for each item:

type Widget struct {
    Label string
    Value string
}

type Config struct {
    // Widget configuration
}

Widget Types

Widgets can display various types of information:

  • Status: Container health status
  • Stats: Usage statistics
  • Links: Quick access links
  • Custom: Provider-specific data

Icon Handling

Icons are handled via IconURL type:

type IconURL struct {
    // Icon URL with various sources
}

// Automatic favicon fetching from item URL

Categories

Default Categories

Category Description
All Contains all items
Favorites User-favorited items
Hidden Items with Show: false
Others Uncategorized items

Custom Categories

Custom categories are created dynamically:

// Adding to custom category
item := &homepage.Item{
    ItemConfig: homepage.ItemConfig{
        Name:     "App",
        Category: "Development",
    },
}
homepageMap.Add(item)
// "Development" category is auto-created

Override Configuration

Items can have override configurations for customization:

// GetOverride returns the effective configuration
func (cfg Item) GetOverride() Item {
    return overrideConfigInstance.GetOverride(cfg)
}

Sorting Methods

Clicks Sort

Sorts by click count (most clicked first):

func (c *Category) sortByClicks() {
    slices.SortStableFunc(c.Items, func(a, b *Item) int {
        if a.Clicks > b.Clicks {
            return -1
        }
        if a.Clicks < b.Clicks {
            return 1
        }
        return strings.Compare(title(a.Name), title(b.Name))
    })
}

Alphabetical Sort

Sorts alphabetically by name:

func (c *Category) sortByAlphabetical() {
    slices.SortStableFunc(c.Items, func(a, b *Item) int {
        return strings.Compare(title(a.Name), title(b.Name))
    })
}

Custom Sort

Sorts by predefined sort order:

func (c *Category) sortByCustom() {
    // Uses SortOrder, FavSortOrder, AllSortOrder fields
}

Data Flow

sequenceDiagram
    participant RouteProvider
    participant HomepageMap
    participant Category
    participant Widget

    RouteProvider->>HomepageMap: Add(Item)
    HomepageMap->>HomepageMap: Add to All
    HomepageMap->>HomepageMap: Add to Category
    alt Item.Favorite
        HomepageMap->>CategoryFavorites: Add item
    else !Item.Show
        HomepageMap->>CategoryHidden: Add item
    end

    User->>HomepageMap: Get Category
    HomepageMap-->>User: Items

    User->>Category: Sort(method)
    Category-->>User: Sorted Items

    User->>Item: Get Widgets
    Item->>Widget: Fetch Data
    Widget-->>Item: Widget Data
    Item-->>User: Display Widgets

Integration Points

The homepage package integrates with:

  • Route Provider: Item discovery from routes
  • Container: Container status and metadata
  • Widgets: Live data display
  • API: Frontend data API
  • Configuration: Default and override configs

Configuration

Active Configuration

var ActiveConfig atomic.Pointer[Config]

Configuration Structure

type Config struct {
    UseDefaultCategories bool
    // ... other options
}

Serialization

The package registers default value factories for serialization:

func init() {
    serialization.RegisterDefaultValueFactory(func() *ItemConfig {
        return &ItemConfig{
            Show: true,
        }
    })
}