Skip to content
/ slate Public

A Python-powered personal dashboard with YAML configuration, server-side rendering, and beautiful themes. Self-hosted, secure, and fast - bringing together all your services in one interface.

License

Notifications You must be signed in to change notification settings

pwelty/slate

Repository files navigation

Slate

Python 3.8+ License: MIT GitHub release

A self-hosted dashboard that outputs pure HTML and CSS. No JavaScript. No framework. No runtime.

Slate fetches data from your services at build time and renders a static HTML file. The result works on anything with an HTML renderer — standard browsers, e-ink displays, screen readers, kiosk screens, curl.

Slate Dashboard

How it works

  1. You define your dashboard layout and widgets in YAML
  2. Slate's Python build step fetches data from your services (weather, tasks, bookmarks, etc.)
  3. Everything is rendered into a single static HTML+CSS file
  4. Serve it from anywhere — any web server, a CDN, a NAS, a Raspberry Pi

API keys stay on the server. They're used at build time, never shipped to the browser. Rebuild on a cron to keep data fresh.

Why Slate instead of Dashy, Homepage, Homarr, etc.?

Every other self-hosted dashboard is a client-side application. Your browser loads a JavaScript bundle, makes API calls to your services, and renders the results. That means:

  • Your API keys are in the browser
  • Every page load triggers a cascade of network requests
  • You need CORS proxies or middleware for most integrations
  • Nothing renders without a JavaScript runtime

Slate takes a fundamentally different approach. All data fetching happens server-side at build time. The output is flat HTML and CSS — no JavaScript required. This makes it:

  • Secure — API keys never leave the server
  • Fast — no client-side fetching, no loading spinners, instant render
  • Universal — works on any device that can render HTML
  • Simple — no runtime, no proxy, no CORS configuration
  • Resilient — the last successful build always works, even if a service is down

Quick start

git clone https://github.com/pwelty/slate.git
cd slate
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt

cp config/dashboard-example.yaml config/dashboard.yaml
# Edit config/dashboard.yaml with your services and API keys

python3 src/scripts/dashboard_renderer.py
python3 src/scripts/serve.py
# Open http://localhost:5173

Configuration

Your dashboard is defined in config/dashboard.yaml:

dashboard:
  title: "My dashboard"
  theme: "paper"

components:
  - id: "weather"
    widget: "weather"
    position: { row: 1, column: 1, width: 4, height: 2 }
    config:
      location: "30033"
      apiKey: "YOUR_OPENWEATHER_KEY"
      units: "fahrenheit"

  - id: "tasks"
    widget: "todoist"
    position: { row: 1, column: 5, width: 4, height: 2 }
    config:
      apiToken: "YOUR_TODOIST_TOKEN"
      limit: 8

Available widgets

Widget Description
weather Current conditions via OpenWeatherMap
forecast Multi-day weather forecast
radar Weather radar map
todoist Tasks with priority indicators
trilium Recent notes from Trilium
linkwarden Bookmarks from Linkwarden
obsidian Notes via Obsidian Local REST API
pihole Pi-hole ad blocking stats (v5 and v6+)
rss RSS feed aggregation
clock Date and time (rendered at build)
link Service shortcuts
text Custom content
image Image display
status-summary System health overview

Themes

Themes are YAML files that define colors, typography, and spacing. Pick one in your config:

Theme Description
paper Clean, classic, document-like
dark Professional dark
light Minimal light
ocean Deep blue
tokyo-night Developer favorite
synthwave 80s neon
retro Terminal aesthetic
minimal-dark Stripped-down dark

Create your own by copying any theme YAML and editing the values.

Development

# Auto-rebuild on file changes
python3 scripts/auto-rebuild.py

# Manual build
python3 src/scripts/dashboard_renderer.py

# Serve locally
python3 src/scripts/serve.py

Deployment

The build output is a static dist/ directory. Serve it however you want:

# Simple Python server
cd dist && python3 -m http.server 8080

# Nginx, Apache, Caddy — just point at dist/

# Docker
docker-compose up

# Tailscale for secure remote access
tailscale serve / http://localhost:5173
# Access at https://slate.yourname.ts.net

Rebuild on a schedule (cron, systemd timer, etc.) to keep widget data fresh.

Creating widgets

Widgets are YAML files in src/widgets/. Each defines a schema, optional data processing (Python), HTML template, and CSS:

extends: "widget"

metadata:
  type: "api"
  description: "My custom widget"

schema:
  apiKey:
    type: "string"
    required: true

dataProcessing:
  generateData: |
    import requests
    response = requests.get("https://api.example.com",
                            headers={"Authorization": config['apiKey']})
    result = response.json()

widget-body: |
  <div class="my-widget">{{ result.data }}</div>

css: |
  .my-widget { color: var(--color-text); }

See widget definitions for the full specification.

Documentation

Alternatives

Slate is one of many self-hosted dashboard projects. These are excellent and may be a better fit depending on your needs:

  • Dashy — highly customizable, 50+ widgets, extensive theming
  • Homepage — modern design, 100+ service integrations
  • Homarr — GUI configuration, user management
  • Heimdall — simple application launcher
  • Homer — minimal static homepage

Slate's approach is different: server-side data fetching with pure HTML+CSS output, no JavaScript runtime required.

Contributing

Contributions are welcome — bug reports, widgets, themes, documentation.

License

MIT License © 2025 Paul Welty

About

A Python-powered personal dashboard with YAML configuration, server-side rendering, and beautiful themes. Self-hosted, secure, and fast - bringing together all your services in one interface.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •