1
FEATURES
MayaChat edited this page 2025-11-24 14:43:28 -05:00

Services Homepage - Features Documentation

Overview

This services homepage provides a modern, feature-rich interface for managing and monitoring your self-hosted services. All features include persistent storage using browser localStorage.


🎯 Core Features

1. Custom Health Check Endpoints

Health checks now support custom endpoints for services that don't respond on the root path.

Configuration

Add the health-path attribute to any service in services.xml:

<service id="jellyfin" 
         name="Jellyfin" 
         proto="http" 
         port="8096" 
         health-path="/health"
         logo="jellyfin.svg" />

Supported attributes:

  • health-path: Custom path to ping (e.g., /api/health, /ping, /status)
  • If not specified, defaults to root path (/)

How It Works

The health-proxy service:

  1. Parses services.xml and finds the service by id
  2. Uses local-ip > tailscale-ip > host for the target
  3. Appends the custom health-path to the URL
  4. Performs a HEAD request to check availability

2. Drag-and-Drop Service Reordering 🖱️

Reorganize your services within each group by dragging and dropping cards.

Usage

  1. Click and hold any service card
  2. Drag it to the desired position within the same group
  3. Release to drop
  4. Order is automatically saved to localStorage

Features

  • Reordering within groups only (maintains organization)
  • Visual feedback during drag (opacity, border highlight)
  • Persistent across browser sessions
  • Per-group order tracking

Reset Order

To reset to default XML order:

localStorage.removeItem('services-order');
location.reload();

3. Collapsible Service Groups 📁

Collapse and expand service groups to focus on what matters.

Usage

  1. Click on any group header (or the ▼ icon)
  2. The group will collapse/expand
  3. State is saved automatically

Features

  • Animated collapse/expand
  • Persistent state per group
  • Visual indicator (rotating arrow)
  • Keyboard accessible

Reset State

localStorage.removeItem('collapsed-groups');
location.reload();

4. Theme System 🎨

Choose from 5 built-in themes or customize your own.

Available Themes

  1. Dark (Default) - Deep blue-gray tones
  2. Light - Clean white and blue
  3. Ocean - Deep teal and aqua
  4. Sunset - Purple and pink gradient
  5. Forest - Green and earth tones

Usage

  1. Click the 🎨 icon in the top-right corner
  2. Select a theme from the menu
  3. Theme is applied immediately and saved

Custom Themes

Themes are defined in js/themes.js. To add a custom theme:

customTheme: {
  name: 'My Theme',
  primary: '#hexcolor',
  secondary: '#hexcolor',
  accent: '#hexcolor',
  text: '#hexcolor',
  textMuted: '#hexcolor',
  border: '#hexcolor',
  cardBg: 'rgba(...)',
  headerBg: 'rgba(...)',
  overlayBg: 'rgba(...)'
}

Add your theme to the themes object and rebuild.


5. Export/Import Configuration 💾

Backup and restore your service configurations with JSON export/import.

Export Configuration

  1. Click 📥 Export button in the top-left
  2. Downloads services-config-YYYY-MM-DD.json file
  3. Contains all services, groups, and settings

Import Configuration

  1. Click 📤 Import button
  2. Select a previously exported JSON file
  3. Downloads a new services.xml file
  4. Replace your existing services.xml and rebuild containers

Export Format

{
  "version": "1.0",
  "exportDate": "2025-11-24T...",
  "tailscaleIp": "100.124.17.41",
  "groups": [
    {
      "name": "Management",
      "services": [
        {
          "id": "portainer",
          "name": "Portainer",
          "proto": "https",
          "port": "9443",
          "logo": "portainer.svg"
        }
      ]
    }
  ]
}

6. Dashboard Widgets 📊

Add live widgets to your homepage header.

Available Widgets

Clock Widget
  • Real-time clock with date
  • Updates every second
  • Always enabled by default
🌤️ Weather Widget
  • Current weather for your location
  • Temperature, conditions, wind, humidity
  • Requires OpenWeatherMap API key (free)
  • Auto-location or custom city
💭 Daily Quote Widget
  • Random inspirational quotes
  • Fetched from quotable.io API
  • Changes on each page load

Configuration

  1. Click ⚙️ Widgets button
  2. Enable/disable widgets with checkboxes
  3. For weather:
    • Get API key from OpenWeatherMap
    • Enter API key
    • Set location to auto or city name (e.g., Toronto)
  4. Click Save & Reload

Settings Storage

All widget settings stored in localStorage:

{
  "clock": {"enabled": true},
  "weather": {
    "enabled": true,
    "apiKey": "your-api-key",
    "location": "auto"
  },
  "quote": {"enabled": false}
}

🛠️ Technical Details

Architecture

┌─────────────────┐
│  Browser        │
│  (HTTPS)        │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Nginx          │◄── Serves static files
│  (Port 8088)    │◄── Reverse proxy /healthcheck
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│  Health Proxy   │
│  (Flask:8081)   │◄── Server-side health checks
│                 │◄── Parses services.xml
└─────────────────┘

Files Structure

services-homepage/
├── index.html                 # Main HTML
├── styles.css                 # Styles with CSS variables
├── services.xml               # Service configuration
├── nginx.conf                 # Nginx config with resolver
├── docker-compose.yml         # Multi-container setup
├── backend/
│   └── health-proxy.py        # Flask health check service
└── js/
    ├── galaxy-background.js   # 3D background
    ├── services-loader.js     # Core service rendering
    ├── drag-drop.js           # Drag-and-drop module
    ├── collapsible-groups.js  # Group collapse module
    ├── themes.js              # Theme system
    ├── export-import.js       # Config backup/restore
    ├── widgets.js             # Dashboard widgets
    ├── search.js              # Search functionality
    ├── keyboard-nav.js        # Arrow key navigation
    └── readme-loader.js       # Markdown rendering

localStorage Keys

Key Purpose Format
services-order Drag-drop order {"GroupName": ["id1", "id2"]}
collapsed-groups Collapsed state {"GroupName": true/false}
selected-theme Active theme "dark"/"light"/"ocean"/...
enabled-widgets Widget settings {clock: {...}, weather: {...}}

📋 services.xml Reference

Root Element

<services tailscale-ip="100.124.17.41">

Attributes:

  • tailscale-ip: Default IP for local services (optional)

Service Element

<service 
  id="unique-id"
  name="Display Name"
  proto="http|https"
  port="8080"
  host="domain.com"
  logo="logo.svg"
  status="maintenance"
  check-health="true|false"
  health-path="/custom/path"
  local-ip="192.168.1.100"
/>

Attributes:

Attribute Required Description Example
id Recommended Unique identifier portainer
name Required Display name Portainer
proto Optional Protocol (default: http) https
port Optional Port number 9443
host Optional Custom hostname/URL cloud.example.com
logo Optional Logo filename in /logos/ portainer.svg
status Optional Manual status override maintenance
check-health Optional Enable health check (default: true) false
health-path Optional Custom health endpoint /api/health
local-ip Optional Override IP for health checks 192.168.1.100

🔧 Troubleshooting

Health Checks Return 502

Problem: Nginx can't resolve the health-proxy container.

Solution: Ensure nginx.conf contains:

resolver 127.0.0.11 valid=30s;

Widgets Not Appearing

Problem: Widgets enabled but not showing.

Solutions:

  1. Check browser console for errors
  2. For weather: Verify API key is correct
  3. Clear localStorage and reconfigure:
    localStorage.removeItem('enabled-widgets');
    location.reload();
    

Drag-and-Drop Not Working

Problem: Cards won't drag.

Solutions:

  1. Ensure JavaScript is enabled
  2. Check browser console for errors
  3. Verify cards have draggable="true" attribute
  4. Try different browser

Theme Not Persisting

Problem: Theme resets after reload.

Solutions:

  1. Check browser allows localStorage
  2. Try incognito/private mode to test
  3. Clear site data and reconfigure

🚀 Future Enhancement Ideas

  • Custom widget creation API
  • Service groups reordering (drag groups)
  • Dark mode auto-switch (time-based)
  • Service uptime statistics
  • Notification system for service outages
  • Mobile app (PWA)
  • Multi-user configurations
  • Service tags and filtering
  • Global search across all services
  • Service dependencies visualization

📝 Changelog

v2.0.0 - 2025-11-24

Added:

  • Custom health check endpoints support
  • Drag-and-drop service reordering
  • Collapsible service groups
  • Theme system (5 themes)
  • Export/import configuration
  • Dashboard widgets (clock, weather, quote)
  • 🐛 Fixed nginx DNS resolver for health-proxy
  • 🐛 Fixed services.xml mount in health-proxy container

v1.0.0 - Previous

  • Basic service listing from XML
  • Automatic health checks
  • Search functionality
  • Keyboard navigation
  • 3D galaxy background
  • README rendering

🤝 Contributing

To add features:

  1. Create new module in /js/
  2. Export functions via window.moduleName
  3. Import in index.html
  4. Initialize in DOMContentLoaded listener
  5. Add styles to styles.css
  6. Document in this file

📄 License

This project is open source. See LICENSE file for details.


Questions or Issues? Check the README.md or open an issue.