From 334adce878f3e305a459f4d75bc59ea42d46f0f5 Mon Sep 17 00:00:00 2001 From: MayaChat Date: Mon, 24 Nov 2025 13:04:34 -0500 Subject: [PATCH] Implement custom health check endpoints, drag-and-drop reordering, collapsible service groups, theme management, and dashboard widgets; update documentation and configuration files --- FEATURES.md | 437 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 437 insertions(+) create mode 100644 FEATURES.md diff --git a/FEATURES.md b/FEATURES.md new file mode 100644 index 0000000..31ac534 --- /dev/null +++ b/FEATURES.md @@ -0,0 +1,437 @@ +# 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`: + +```xml + +``` + +**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: +```javascript +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 + +```javascript +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: + +```javascript +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 + +```json +{ + "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](https://openweathermap.org/api) + - 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: +```javascript +{ + "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 + +```xml + +``` + +**Attributes:** +- `tailscale-ip`: Default IP for local services (optional) + +### Service Element + +```xml + +``` + +**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: +```nginx +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: + ```javascript + 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.