Files
Homepage/README.md

478 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Services Homepage
A lightweight, self-hosted dashboard for quick access to your Docker services with a modern holographic UI design.
![License](https://img.shields.io/badge/license-MIT-blue.svg)
![Docker](https://img.shields.io/badge/docker-required-blue.svg)
## Features
- 🎨 **Holographic Glass Design** - Modern liquid glass buttons with animated shimmer effects
- 🎯 **Dynamic Service Loading** - Services configured via simple XML file
- 🔍 **Smart URL Resolution** - Automatic handling of ports, protocols, and hostnames
- 🎭 **Icon Integration** - Includes Simple Icons pack (3000+ brand logos)
- 📱 **Responsive Layout** - Works seamlessly on desktop and mobile
- 🐳 **Docker-Ready** - Single-container deployment with nginx
-**Lightweight** - Minimal resources, fast loading
- 🔎 **Search & Filter** - Instant search with keyboard shortcut (press `/`)
- **Connection Details** - Info button shows hostname/port for each service
- 🎮 **Keyboard Navigation** - Arrow keys to navigate, Enter to open, Esc to clear
- 🟢 **Status Indicators** - Optional visual status (online/offline/maintenance)
- 🏥 **Automatic Health Checks** - Real-time ping tests to detect service availability
- 📂 **Service Groups** - Organize services into categorized sections
## Quick Start
### 1. Deploy with Docker Compose
```bash
docker-compose up -d
```
The homepage will be available at `http://localhost:8088`
### 2. Configure Your Services
Edit `services.xml` to add your services organized into groups:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<services>
<group name="Management">
<service
name="Portainer"
proto="https"
port="9443"
logo="portainer.svg"
/>
</group>
<group name="Media">
<service
name="Jellyfin"
proto="http"
port="8096"
host="jellyfin.example.com"
logo="jellyfin.svg"
/>
</group>
</services>
```
Or use services without groups (they'll appear in a single grid):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<services>
<service name="Portainer" proto="https" port="9443" logo="portainer.svg" />
<service name="Jellyfin" proto="http" port="8096" logo="jellyfin.svg" />
</services>
```
### 3. Restart to Apply Changes
```bash
docker-compose restart
```
## Configuration Guide
### Service Attributes
| Attribute | Required | Description | Example |
|-----------|----------|-------------|---------|
| `name` | Yes | Display name for the service | `"Nextcloud"` |
| `proto` | No | Protocol (http/https) | `"https"` (default: `"http"`) |
| `port` | No | Port number | `"8080"` |
| `host` | No | Custom hostname or full URL | `"nextcloud.example.com"` |
| `logo` | No | Icon filename in `/logos/` | `"nextcloud.svg"` |
| `status` | No | Set to `"maintenance"` to skip health check | `"maintenance"` |
| `check-health` | No | Enable/disable auto health check | `"true"` (default) or `"false"` |
### URL Resolution Logic
The service URL is built using this priority:
1. **Full URL** - If `host` starts with `http://` or `https://`, use as-is
2. **Hostname with Port** - If `host` contains `:port`, use `proto://host:port`
3. **Hostname Only** - If `host` is set (no port), use `https://host` (ignores `proto` and `port`)
4. **Fallback** - Use current page hostname with specified `proto` and `port`
### Examples
```xml
<!-- Full URL (ignores proto and port) -->
<service name="Example" host="https://example.com/app" />
<!-- Public domain (defaults to HTTPS) -->
<service name="Nextcloud" host="cloud.example.com" logo="nextcloud.svg" />
<!-- Custom port on domain -->
<service name="Jellyfin" host="media.example.com:8096" proto="http" logo="jellyfin.svg" />
<!-- Local service (uses page hostname) -->
<service name="Portainer" proto="https" port="9443" logo="portainer.svg" />
<!-- Service with status indicator -->
<service name="Home Assistant" proto="http" port="8123" logo="homeassistant.svg" status="online" />
```
## Keyboard Shortcuts
- **`/`** - Focus the search bar (press from anywhere)
- **Arrow Keys** - Navigate between service cards (Up/Down/Left/Right)
- **Enter** - Open the selected service in a new tab
- **Esc** - Clear the current selection
## Info Button
When a service has both a hostname and port configured, a small info button (ⓘ) appears in the bottom-right corner of the card. Click it to view connection details including:
- Service name
- Hostname
- Port number
- Protocol
## Status Indicators
Services are automatically checked for availability when the page loads. Status indicators appear in the top-right corner of each card:
```xml
<!-- Automatic health check (default behavior) -->
<service name="Jellyfin" proto="http" port="8096" logo="jellyfin.svg" />
<!-- Manual maintenance mode (skips health check) -->
<service name="Nextcloud" status="maintenance" host="cloud.example.com" logo="nextcloud.svg" />
<!-- Disable health check for a service -->
<service name="Legacy App" check-health="false" proto="http" port="8080" logo="app.svg" />
```
Status colors:
- **Gray spinning** (checking) - Currently testing service availability
- **Green pulsing** (online) - Service responded successfully to health check
- **Red** (offline) - Service failed to respond or timed out (5 seconds)
- **Orange** (maintenance) - Manual maintenance mode, health check skipped
### How Health Checks Work
- Each service is automatically pinged when the page loads
- Uses a 5-second timeout per service
- Checks run in parallel for all services
- Services marked `status="maintenance"` skip the health check
- Set `check-health="false"` to disable checking for specific services
- No server-side component needed - runs entirely in the browser
## Service Groups
Organize your services into categorized sections for better organization:
```xml
<services>
<group name="Management">
<service name="Portainer" proto="https" port="9443" logo="portainer.svg" />
<service name="Uptime Kuma" proto="http" port="3001" logo="uptime-kuma.svg" />
</group>
<group name="Media">
<service name="Jellyfin" proto="http" port="8096" logo="jellyfin.svg" />
<service name="Transmission" proto="http" port="9091" logo="transmission.svg" />
</group>
<group name="Storage">
<service name="Nextcloud" host="cloud.example.com" logo="nextcloud.svg" />
<service name="FileBrowser" proto="http" port="8986" logo="filebrowser.svg" />
</group>
</services>
```
### Group Features
- **Categorization**: Group related services together (Media, Management, Development, etc.)
- **Visual Separation**: Each group has a styled header with an accent underline
- **Smart Search**: Searching filters services and hides empty groups automatically
- **Backward Compatible**: Services without groups still work (displayed in a single grid)
- **Flexible**: Use as many or as few groups as needed
### Group Tips
- Use clear, descriptive group names (e.g., "Media Services" instead of "Group 1")
- Keep related services together for easier navigation
- Groups appear in the order defined in the XML
- Empty groups (no services) are automatically hidden
## Icon Management
### Using Included Icons
The repository includes Simple Icons (3000+ brand logos). Available icons are in:
```
logos/simple-icons/icons/
```
### Adding Custom Icons
1. Add your SVG file to the `logos/` directory
2. Reference it in `services.xml`:
```xml
<service name="MyApp" logo="myapp.svg" />
```
### Icon Styling
All icons are automatically styled white using CSS filters. To customize:
Edit `styles.css` and modify the `.card .logo` rule:
```css
.card .logo {
filter: brightness(0) invert(1); /* White icons */
/* OR */
filter: hue-rotate(180deg); /* Color shift */
}
```
## Customization
### Theme Colors
Edit CSS variables in `styles.css`:
```css
:root {
--bg: #0f1720; /* Background color */
--card: #0b1220; /* Card background */
--accent: #4f46e5; /* Accent color (purple) */
--muted: #94a3b8; /* Muted text */
}
```
### Holographic Effects
The holographic button effects include:
- **Shimmer Animation** - Continuous light sweep (8s loop, 3s on hover)
- **Gradient Background** - Purple/pink gradient blend
- **Glowing Border** - Animated gradient border on hover
- **Backdrop Blur** - Glass-like frosted effect
To adjust shimmer speed, modify the `@keyframes shimmer` animation:
```css
.card::before {
animation: shimmer 8s infinite linear; /* Change 8s to adjust speed */
}
```
### Layout
Change grid responsiveness in `styles.css`:
```css
.grid {
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
/* Adjust minmax() to change card width */
}
```
## File Structure
```
services-homepage/
├── docker-compose.yml # Docker deployment config
├── Dockerfile # Custom nginx build (if needed)
├── index.html # Main HTML page
├── styles.css # Holographic UI styles
├── services.xml # Service definitions
├── README.md # This file
├── LICENSE # License information
└── logos/ # Icon directory
├── simple-icons/ # Simple Icons pack (3000+ logos)
├── default.svg # Fallback icon
├── gitea.svg
├── jellyfin.svg
├── nextcloud.svg
└── ...
```
## Updating Icons
### Replace All Icons with Simple Icons
```bash
cd logos
for f in *.svg; do
basename=$(basename "$f" .svg)
match=$(find simple-icons/icons -type f -iname "*${basename}*.svg" -print -quit)
[ -n "$match" ] && cp "$match" "$f" && echo "Updated: $f"
done
```
### Find Available Icons
```bash
ls logos/simple-icons/icons/ | grep -i "keyword"
```
## Backup and Recovery
Icon backups are automatically created in:
```
logos/backup-YYYYMMDD-HHMMSS/
```
To restore from backup:
```bash
cp logos/backup-20251123-231406/*.svg logos/
docker-compose restart
```
## Troubleshooting
### Cloudflare, HTTPS and Mixed Content
If you're serving the homepage over HTTPS (for example, via Cloudflare), your browser will block active (programmatic) HTTP requests to local IPs — this is "mixed content". That can cause the health checks for local services to fail or to be marked offline.
Recommendations:
- Enable HTTPS for your local services (e.g., configure TLS or use a reverse proxy with a valid certificate) and/or use Cloudflare Tunnel to serve the service with a domain and TLS.
- Or configure a server-side proxy that performs health checks and serves the results over HTTPS (for example, add a proxy endpoint in your nginx config and proxy_pass to the local IP/port); the browser will then make a same-origin secure request to the proxy rather than directly to the IP.
- In `services.xml`, use the `tailscale-ip` attribute to supply an easily-editable Tailscale IP for local services that should be used for links and health checks.
- In `services.xml`, use the `tailscale-ip` attribute to supply an easily-editable Tailscale IP for local services that should be used for links and health checks.
Per-service `local-ip` override:
- If a specific service has a `local-ip` attribute (for example, `local-ip="192.168.2.180"`), the server-side health proxy will use that local IP for the health check. This allows per-service control when the internal IP differs from the household-wide Tailscale IP or when services are bound to different hosts.
Cloudflare Insights & CORS:
- If you see console errors about `static.cloudflareinsights.com` or messages like "CORS request did not succeed" or "integrity mismatch", this is likely a script injected by Cloudflare. This is not part of the homepage codebase and is injected by Cloudflare's edge. You can disable Cloudflare Analytics/Insights or adjust settings in the Cloudflare dashboard to remove or avoid that script if it's causing issues with CSP or integrity.
### Services Not Loading
1. Check `services.xml` syntax:
```bash
xmllint --noout services.xml
```
2. Check browser console for errors (F12)
3. Verify file permissions:
```bash
chmod 644 services.xml index.html styles.css
chmod 755 logos/
```
### Icons Not Displaying
1. Verify icon exists:
```bash
ls -lh logos/youricon.svg
```
2. Check icon reference in `services.xml` matches filename exactly
3. Clear browser cache (Ctrl+Shift+R)
### Container Issues
```bash
# View logs
docker logs services-homepage
# Restart container
docker-compose restart
# Rebuild if files changed
docker-compose up -d --force-recreate
```
## Performance
- **Image Size**: ~45MB (nginx:alpine base)
- **Memory Usage**: ~5-10MB
- **Load Time**: <100ms (local network)
- **Icons**: Cached by browser after first load
## Browser Support
- ✅ Chrome/Edge 90+
- ✅ Firefox 88+
- ✅ Safari 14+
- ✅ Mobile browsers (iOS Safari, Chrome Android)
## Security
- All volumes mounted read-only (`:ro`)
- No external dependencies at runtime
- Logs automatically rotated (5MB max, 2 files)
- CORS not enabled (same-origin only)
## Advanced Usage
### Custom Nginx Config
Create `nginx.conf` and mount it:
```yaml
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
```
### Adding Authentication
Use a reverse proxy (Nginx Proxy Manager, Caddy, Traefik) with basic auth:
```nginx
location / {
auth_basic "Services";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://services-homepage:80;
}
```
### Dynamic Port Updates
For services with dynamic ports (e.g., Transmission behind VPN), use environment variables:
```xml
<service name="Transmission" proto="http" port="${TRANS_PORT}" logo="transmission.svg" />
```
Then update via script or use a template processor.
## Contributing
Contributions welcome! Completed features:
- ✅ Search/filter functionality with keyboard shortcut
- ✅ Keyboard navigation (arrow keys, Enter, Esc)
- ✅ Service status indicators (online/offline/maintenance)
- ✅ Automatic health checks with ping tests
- ✅ Info button showing connection details
- ✅ Service groups/categories
Areas for future improvement:
- Service health checks via custom endpoints
- Drag-and-drop reordering within groups
- Collapsible group sections
- Custom themes/color schemes
- Export/import service configurations
- Dashboard widgets (time, weather, etc.)
## License
MIT License - See LICENSE file for details
## Credits
- **Icons**: [Simple Icons](https://simpleicons.org/) (CC0 1.0 Universal)
- **Design Inspiration**: Holographic UI by vishnu137 on CodePen
- **Web Server**: nginx Alpine
## Support
For issues, questions, or suggestions:
1. Check this README first
2. Review browser console for errors
3. Check Docker logs: `docker logs services-homepage`
4. Verify `services.xml` syntax
---
**Version**: 1.0.0
**Last Updated**: November 23, 2025