A PS3 XrossMediaBar-inspired homelab dashboard. Animated nebula background, full keyboard and touch navigation, per-user preferences, admin-locked settings, and a single Docker container deployment.
Desktop — XMB horizontal category bar with animated nebula background
Mobile — horizontal category pill strip with swipeable item cards
- XMB layout — horizontal category bar, vertical item list, smooth transitions
- Animated nebula background — drifting gas clouds, twinkling stars, per-category accent glow
- Full keyboard navigation — arrow keys for categories/items, Enter to open
- Mobile responsive — touch-friendly pill strip, swipe left/right to change category, tap to open
- Browser tab title — syncs with your dashboard title setting
- Preferences panel — press
Por Settings → Preferences- 6 nebula themes: Default · Crimson · Aurora · Stellar · Ember · Void
- Background intensity: Dim / Normal / Vivid
- Star density: Off / Normal / Dense
- Font size: S / M / L
- Show/hide service descriptions
- Clock format: Auto / 12h / 24h
- Animation speed: Normal / Slow / Off
- All preferences stored in
localStorage— per-browser, instant, no save button
- Add, rename, recolour, and reorder categories
- Add, edit, and remove services
- Drag-to-reorder services within a category
- Icon picker — search 400+ icons from the homarr-labs/dashboard-icons repository, paste a URL, or upload your own image
- Admin-only services — hide individual services from non-admin users (filtered server-side)
- Favicon editor — set a custom favicon via URL or file upload
- Dashboard title and clock format settings
- Single Docker container — Node.js + Express backend
- Persistent config — saved to a Docker volume, survives restarts and image updates
- JWT authentication — 8-hour tokens, configurable secret
- GitHub Actions — auto-builds and pushes to
ghcr.ioon every push tomain - Traefik-ready — labels included in
docker-compose.yml
| Icon | Key | Icon | Key |
|---|---|---|---|
| 🌐 Network | network |
🎮 Gaming | game |
| 💾 Storage | storage |
🎵 Music | music |
| 🖥️ Server | server |
📷 Photos | photo |
| 📊 Monitor | monitor |
📚 Books | book |
| 🎬 Media | media |
☁️ Cloud | cloud |
| 💻 Code / Dev | code |
🛡️ Security | security |
| ⚙️ Settings | settings |
🏠 Smart Home | home |
| 🔧 Tools | tools |
||
| 🗄️ Database | database |
||
| ⌨️ Terminal | terminal |
git clone https://github.com/artech7/xmb-dashboard.git
cd xmb-dashboard
npm install
node server.js
# Visit http://localhost:8484docker compose up -d --build
# Visit http://localhost:8484# After first push, the GitHub Action builds the image automatically.
# In docker-compose.yml, swap the build: block for:
# image: ghcr.io/artech7/xmb-dashboard:latest
docker compose up -d- Push this repo to GitHub (see below)
- Wait for the GitHub Action to build the image (~1 min)
- Make the package public: GitHub → Packages →
xmb-dashboard→ Package settings → Change visibility → Public - In Dockhand, create a stack with the
docker-compose.ymlcontents - Set
image: ghcr.io/artech7/xmb-dashboard:latestand remove thebuild:block - Set environment variables and deploy
Updating: Dockhand → Stacks → xmb-dashboard → Pull & Restart
| Variable | Default | Description |
|---|---|---|
ADMIN_PASSWORD |
admin |
Admin panel password — change before deploying |
JWT_SECRET |
xmb-change-this-secret |
Token signing secret — change before deploying |
PORT |
8484 |
Server listen port |
version: "3.8"
services:
xmb-dashboard:
image: ghcr.io/artech7/xmb-dashboard:latest
container_name: xmb-dashboard
restart: unless-stopped
ports:
- "8484:8484"
environment:
- ADMIN_PASSWORD=yourpassword
- JWT_SECRET=your-long-random-secret
- PORT=8484
volumes:
- /volume1/docker/xmb:/app/data
networks:
- xmb-net
networks:
xmb-net:
driver: bridgeControl Panel → Login Portal → Advanced → Reverse Proxy → Create:
| Field | Value |
|---|---|
| Source protocol | HTTPS |
| Source hostname | dash.yournas.local |
| Source port | 443 |
| Destination protocol | HTTP |
| Destination hostname | localhost |
| Destination port | 8484 |
On first boot, data/config.json is seeded from www/config.json. All edits are made through the admin panel and saved back to the volume. The server automatically injects any missing system items (Preferences, Admin Panel) on startup.
{
"title": "HOMELAB",
"clockFormat": "24h",
"favicon": "",
"categories": [
{
"id": "network",
"name": "Network",
"icon": "network",
"color": "#00c8ff",
"items": [
{
"name": "Router",
"url": "http://192.168.1.1",
"desc": "Gateway / Admin UI",
"icon": "router",
"adminOnly": false
}
]
}
]
}| Key | Action |
|---|---|
← / → |
Switch category |
↑ / ↓ |
Select item |
Enter |
Open selected item |
P |
Open Preferences |
| Key | Action |
|---|---|
↑ / ↓ |
Move between rows |
← / → |
Move between options |
Enter / Space |
Select option |
Esc |
Close |
| Gesture | Action |
|---|---|
| Swipe left / right | Switch category |
| Tap item | Open service |
| Tap category pill | Switch category |
Access via:
- Settings category → Admin Panel
- Direct URL:
http://yourhost:8484/admin
Default password: admin — set via ADMIN_PASSWORD environment variable.
cd xmb-dashboard
git remote add origin https://github.com/artech7/xmb-dashboard.git
git push -u origin main --forceAfter that, plain git push works for all future updates. The GitHub Action at .github/workflows/docker.yml builds and pushes the Docker image to ghcr.io automatically on every push to main.
xmb-dashboard/
├── .github/
│ └── workflows/
│ └── docker.yml # Auto-build → ghcr.io on push to main
├── data/
│ └── .gitkeep # Runtime config saved here (gitignored)
├── www/
│ ├── index.html # Full dashboard UI (XMB + settings + prefs)
│ ├── config.json # Seed config — edit for defaults
│ ├── favicon.svg # Default XMB favicon
│ └── favicon.png
├── .dockerignore
├── .gitignore
├── Dockerfile # node:22-alpine
├── docker-compose.yml
├── package.json
├── README.md
└── server.js # Express: static files + config API + JWT auth
MIT