Open-source customizable dashboard for TV displays, written in Rust.
do-board is a web application designed to run on a television screen. It displays configurable widgets in real time: public transport schedules, promotion birthdays, embedded dashboards (Grafana, etc.), weather, planning, and more.
Rust workspace with two crates and a shared types library:
do-board/
βββ backend/ # REST API (Axum, port 3000)
βββ frontend/ # SPA compiled to WebAssembly (Dioxus)
βββ shared/ # Types shared between backend and frontend
βββ helm/ # Kubernetes Helm chart
| Crate | Role | Technology |
|---|---|---|
backend |
HTTP API, data aggregation | Axum, Tokio |
frontend |
Browser UI, widget rendering | Dioxus, WASM |
shared |
Common data types (Dashboard, Widget, β¦) | Serde |
| Type | Description |
|---|---|
weather |
Current weather conditions |
transport |
Public transport schedules |
birthdays |
Promotion birthdays |
iframe |
Embedded external URL (Grafana, β¦) |
clock |
Current time and date |
The only prerequisite is Docker with Compose v2.
Hot-reload on every file change: cargo-watch recompiles the backend in a few seconds, dx serve reloads the frontend WASM in the browser.
# First run - builds the dev images (takes ~10 minutes, cached afterwards)
docker compose -f docker-compose.dev.yml up --build
# Subsequent runs
docker compose -f docker-compose.dev.yml up| Service | URL | Reloads on change to⦠|
|---|---|---|
| Frontend | http://localhost:8080 | frontend/src/**, frontend/input.css |
| Backend | http://localhost:3000 | backend/src/**, shared/src/** |
Builds optimised release images (Rust binary + nginx serving the WASM bundle).
docker compose up --build| Service | URL |
|---|---|
| Frontend | http://localhost:80 |
| Backend | http://localhost:3000 |
Copy and edit before starting:
cp .env.example .env| Variable | Default | Description |
|---|---|---|
ADMIN_EMAIL |
admin@example.com |
Email of the initial admin account |
ADMIN_PASSWORD |
changeme |
Password of the initial admin account |
JWT_SECRET |
change_me_in_production |
Secret used to sign JWT tokens - change this in production |
The initial admin account is created automatically on first start if it does not already exist.
A Helm chart is provided in helm/do-board to deploy do-board on a Kubernetes cluster. It deploys:
- a
backendDeployment + Service (Axum API) - a
frontendDeployment + Service (nginx serving the WASM bundle, reverse-proxying/apiand/wsto the backend) - an optional
Ingressexposing the frontend - a bundled PostgreSQL
StatefulSet+ Service (plainpostgresimage, can be disabled in favour of an external/managed database)
Container images are built and pushed to the GitHub Container Registry by .github/workflows/docker.yml:
| Trigger | Tags pushed |
|---|---|
Push to main |
latest, sha-<short-sha> |
GitHub Release (vX.Y.Z) |
X.Y.Z, X.Y, X |
Images: ghcr.io/do-2k25-28/do-board-backend and ghcr.io/do-2k25-28/do-board-frontend. If the packages are private, create an imagePullSecrets entry (see below) before installing the chart.
- A Kubernetes cluster and kubectl configured to reach it
- Helm β₯ 3.8
- An ingress controller (e.g. Traefik) if you want to enable the bundled
Ingress
cd helm/do-board
helm install do-board . \
--namespace do-board --create-namespace \
--set env.jwtSecret="$(openssl rand -hex 32)" \
--set env.adminEmail=admin@example.com \
--set env.adminPassword="$(openssl rand -hex 16)" \
--set ingress.enabled=true \
--set ingress.className=traefik \
--set ingress.host=do-board.example.comWithout ingress.enabled, reach the app with:
kubectl port-forward -n do-board svc/do-board-frontend 8080:80| Value | Default | Description |
|---|---|---|
backend.image.repository |
ghcr.io/do-2k25-28/do-board-backend |
Backend image |
frontend.image.repository |
ghcr.io/do-2k25-28/do-board-frontend |
Frontend image |
backend.image.tag / frontend.image.tag |
"" (β .Chart.AppVersion, i.e. latest) |
Override to pin a release tag, e.g. 1.2.0 or sha-abcdef0 |
imagePullSecrets |
[] |
Names of secrets to pull private GHCR images |
env.jwtSecret / env.adminEmail / env.adminPassword |
see values.yaml |
App credentials - override in production, or set existingSecret to a Secret you manage yourself |
config.gtfsStaticUrl / config.gtfsRtUrl |
Montpellier TaM GTFS feeds | Public transport widget data source |
postgresql.enabled |
true |
Set to false to use an external database via externalDatabase.url |
postgresql.persistence.size |
4Gi |
Size of the PVC for the bundled PostgreSQL data volume |
ingress.enabled |
false |
Expose the frontend through an Ingress |
See helm/do-board/values.yaml for the full list, and run helm show values helm/do-board or helm template helm/do-board to inspect the rendered manifests before installing.
helm upgrade do-board helm/do-board -n do-board -f my-values.yaml
helm uninstall do-board -n do-board- Rust β₯ 1.80
- Dioxus CLI -
cargo install dioxus-cli - Tailwind CSS CLI - standalone binary, no Node.js required
wasm32-unknown-unknowntarget- A running PostgreSQL instance
rustup target add wasm32-unknown-unknown
cargo install dioxus-cli
# Tailwind CSS standalone binary (Linux x86_64)
curl -sL https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 \
-o ~/.local/bin/tailwindcss && chmod +x ~/.local/bin/tailwindcssexport DATABASE_URL=postgresql://user:password@localhost:5432/doboard
export ADMIN_EMAIL=admin@example.com
export ADMIN_PASSWORD=changeme
export JWT_SECRET=my_secret
cargo run -p backend
# API available at http://localhost:3000Two terminals running in parallel:
# Terminal 1 - Tailwind CSS (watch mode)
cd frontend
tailwindcss -i input.css -o assets/tailwind.css --watch
# Terminal 2 - Dioxus dev server
cd frontend
API_BASE=http://localhost:3000 dx serve
# UI available at http://localhost:8080MIT - see LICENSE