A lightweight, memory-efficient dashboard for your homelab. Built with SvelteKit for fast performance and simple YAML configuration.
# Install dependencies
bun install
# Development server (http://localhost:5173)
bun dev
# Build for production
bun run build
# Preview production build
bun preview
Quick Start:
# 1. Clone repository
git clone https://github.com/your-username/liteda.git
cd liteda
# 2. Start with Docker Compose (config auto-initialized on first run)
docker compose up -d
# 3. Visit http://localhost:3000
Configuration:
Config files are automatically created in ./config/ on first run with sensible defaults.
To customize:
# Edit settings
nano config/settings.yaml
# Edit services
nano config/services.yaml
# Restart to apply changes
docker compose restart
Manual Docker Run:
# Build image
docker build -t liteda .
# Create config directory
mkdir -p config
# Run container
docker run -d \
--name liteda \
-p 3000:3000 \
-v ./config:/app/config \
--restart unless-stopped \
liteda
Local Development with Docker:
For development with hot reload:
# Use dev compose file
docker compose -f docker-compose.dev.yml up
# Visit http://localhost:5173 (Vite dev server)
This mounts your source code into the container for live reload.
Liteda is a Progressive Web App (PWA) that can be installed on any device:
Desktop (Chrome/Edge/Brave):
Ctrl/Cmd + Shift + AMobile (iOS - Safari):
Mobile (Android - Chrome):
Features:
See docs/PWA.md for detailed documentation.
Generate PWA Icons:
# Requires Inkscape or ImageMagick
bun run pwa:icons
Config hot reload is enabled by default in dev mode, disabled in production.
# Development (default: enabled)
bun dev
# Development (disable)
AUTO_RELOAD=false bun dev
# Production (enable - not recommended)
AUTO_RELOAD=true bun preview
Behavior:
AUTO_RELOAD=true to enableWhat's reloaded:
All configuration files are in the config/ directory:
config/
āāā settings.yaml # Global settings, theme, layout
āāā services.yaml # Default home page services
āāā pages/ # Additional pages
āāā media.yaml # YAML page
āāā infra.yaml
āāā notes.md # Markdown page with frontmatter
config/settings.yaml
title: My Homelab
theme: dark # light, dark, auto
# Optional background image
background:
image: https://example.com/bg.jpg
opacity: 0.3
blur: 2
layout:
columns: 3 # Default column count for service groups
# Customize header bar with gadgets
header:
- type: resources # System monitor
- type: spacer # Push items to the right
- type: weather # Weather display
vars:
latitude: 25.0330
longitude: 121.5654
label: "Taipei"
- type: search # Global search (āK)
- type: theme-switcher # Theme toggle
# Define pages (tabs)
pages:
- id: home
name: Home
icon: home
file: services.yaml
- id: media
name: Media
icon: play-circle
file: pages/media.yaml
- id: notes
name: Notes
icon: file-text
file: pages/notes.md
config/services.yaml or config/pages/media.yaml
# Flat service group
- name: Quick Access
columns: 2
equalHeight: true # Cards in same row have equal height
items:
- name: Portainer
icon: portainer
url: https://portainer.local
description: Container management
# Optional: Add live data widget
widget:
type: portainer
interval: 10000 # Poll every 10s (has server-side cache)
vars:
url: https://portainer.local
key: "your-api-key"
env: 1
- name: Jellyfin
icon: jellyfin
url: https://jellyfin.local
widget:
type: jellyfin
interval: 10000
vars:
url: https://jellyfin.local
key: "your-api-key"
# Nested service groups
- name: Infrastructure
icon: server
columns: 2
groups:
- name: Monitoring
items:
- name: Grafana
icon: grafana
url: https://grafana.local
- name: Management
items:
- name: Proxmox
icon: proxmox
url: https://pve.local
# Bookmarks style (compact tags)
- name: Quick Links
type: bookmarks
items:
- name: Google
url: https://google.com
icon: google
- name: GitHub
url: https://github.com
icon: github
Create .md files in config/pages/ with frontmatter for mixed content:
config/pages/notes.md
---
blocks:
tools:
name: Common Tools
type: services
columns: 2
items:
- name: Portainer
url: https://portainer.local
icon: portainer
widget:
type: portainer
interval: 10000
vars:
url: https://portainer.local
key: "your-api-key"
---
# Server Documentation
Some notes about your homelab setup...
## Service Cards Injection
Use block markers to inject service groups:
::: block:tools :::
More content below the service cards...
Organize header gadgets with flexible alignment:
layout:
header:
# Left-aligned group
- type: group
vars:
align: left # left, center, right
items:
- type: resources
vars:
cpu: true
memory: true
refresh: 10000
- type: weather
vars:
latitude: 25.0330
longitude: 121.5654
# Spacer pushes to the right
- type: spacer
# Right-aligned group
- type: group
vars:
align: right
items:
- type: search
- type: theme-switcher
Widgets display live data from your services. All widgets support:
interval)Infrastructure (7 widgets)
portainer - Container management statsproxmox - VM/LXC resource usagenginx-proxy-manager - Proxy hosts countcloudflared - Tunnel statusadguard - DNS queries and blocking statsgrafana - Dashboard and datasource countuptime-kuma - Service uptime monitoringMedia (6 widgets)
jellyfin - Media library statsplex - Library and stream infosonarr - TV series monitoringradarr - Movie monitoringqbittorrent - Torrent statstautulli - Plex activity trackingš See Widget Development Guide for creating custom widgets
Gadgets are header bar components. Available gadgets:
title - Display site title from settingsspacer - Flexible space (push items right)theme-switcher - Light/dark mode togglesearch - Global search (āK / Ctrl+K)resources - System monitor (CPU, memory, disk, temp)weather - Current weather with detailed popovergroup - Organize gadgets with alignment (left/center/right)š See Gadget Development Guide for creating custom gadgets
JSON schemas are automatically generated during build for autocomplete and validation.
Schemas are located in config/schemas/:
settings.schema.json - For settings.yamlservices.schema.json - For service YAML filesIn VS Code, schemas are auto-applied via .vscode/settings.json.
To manually regenerate schemas:
bun run schema
Memory Usage:
Caching System:
interval)Configuration Example:
widget:
type: portainer
interval: 10000 # Poll every 10s (client-side)
vars:
url: https://portainer.local
key: "your-api-key" # Secure: never sent to browser
Server caches the API response for 10s, so multiple clients share the same data.
If you can't edit config/settings.yaml after starting with Docker:
Quick Fix (Recommended):
sudo chown -R $(id -u):$(id -g) config/
Alternative (Permanent):
Edit docker-compose.yml and uncomment the user: line:
user: "${UID:-1000}:${GID:-1000}"
Then restart:
docker compose down && docker compose up -d
If using Docker:
host.docker.internal instead of localhost:widget:
vars:
url: http://host.docker.internal:9000 # Not localhost:9000
General checks:
varsdocker logs litedaDocker:
docker compose restart
Bun (with AUTO_RELOAD=false):
# Stop and restart
bun preview
Check if the server is running:
# Docker
docker logs liteda
# Test health endpoint
curl http://localhost:3000/health
MIT License - see LICENSE file for details