Skip to main content

Setup & running

How to get horrible-dashboard running from a fresh clone — the browser layout and the desktop (Tauri) layout share one frontend, so most of the setup is common.

Kept in sync with package.json

The Scripts reference below mirrors the scripts block in the repo-root package.json. If you add, rename, or change a pnpm script, update this page in the same change (a Stop hook flags a package.json change that doesn't touch docs/). See the sync policy.

Prerequisites

ToolVersionNotes
Node.jsLTS (≥ 20)Runtime for pnpm and Vite.
pnpm10.28.2Pinned via packageManager. Easiest: corepack enable (uses the pinned version automatically).
Python≥ 3.12The backend (requires-python = ">=3.12").
uvlatestPython package/venv manager — install guide. The backend is managed with uv, never pip.
Rust + Tauri prereqsstable toolchainDesktop layout only. rustup plus the Tauri v2 system dependencies (WebView2 — preinstalled on Windows 11; webkit2gtk on Linux; Xcode Command Line Tools on macOS). The Tauri CLI itself comes from pnpm install.

Install

corepack enable # make the pinned pnpm available (first time only)
pnpm install # JS deps for every workspace (apps/*, packages/*)
uv sync # backend Python deps + a local .venv

Optional: uv sync --extra webrtc adds the WebRTC data-channel transport for the peer fabric (heavy native deps, so it's opt-in).

Run the browser layout

pnpm dev # backend + Vite UI together

Open http://localhost:5173. pnpm dev (via scripts/dev.mjs) starts the FastAPI backend on :8000 and the Vite UI on :5173, which proxies /api and /ws to the backend — so API panels work out of the box. Backend health check: GET http://localhost:8000/api/health.

  • pnpm dev:web — UI only, when a backend is already running.
  • pnpm dev:lan — bind both servers to 0.0.0.0 so other machines can reach this node (needed for the peer fabric / collaboration).

Run the desktop layout (Tauri)

pnpm dev:desktop # runs `tauri dev`

The Tauri shell supervises the backend itself (apps/desktop/src-tauri/src/backend.rs): it spawns uvicorn, or reuses one already running on :8000 — no separate backend start needed. The first run compiles Rust and takes several minutes; that's expected.

Production builds

pnpm build # static web bundle (apps/web/dist)
pnpm build:desktop # native desktop installers (Tauri)

Backend on its own

pnpm dev already runs the backend; start it standalone only when iterating on Python:

uv run uvicorn backend.app:app --reload --reload-dir backend --reload-exclude "logs/*" --port 8000 # dev server
uv run pytest # backend tests
uv run ruff format . && uv run ruff check --fix . # format + lint Python

--reload-dir backend scopes the watcher to Python source only; --reload-exclude additionally excludes logs/ (where backend.log lives) so writing a log line never triggers a reload loop.

Checks

pnpm typecheck # all TS workspaces
pnpm lint # ESLint
pnpm format # Prettier (writes)
uv run pytest # backend tests

Scripts reference

Every script in the repo-root package.json:

ScriptUnderlying commandPurpose
pnpm devnode scripts/dev.mjsFull browser stack: FastAPI backend and Vite UI together (localhost:5173).
pnpm dev:webpnpm --filter @horrible/web devFrontend only (assumes a backend is already up).
pnpm dev:lannode scripts/dev.mjs --host 0.0.0.0Same as dev but bound to 0.0.0.0 for LAN / peer-fabric access.
pnpm dev:desktoppnpm --filter @horrible/desktop devDesktop layout (tauri dev); the shell supervises the backend.
pnpm buildpnpm --filter @horrible/web buildProduction web bundle.
pnpm build:desktoppnpm --filter @horrible/desktop buildNative desktop build (tauri build).
pnpm build:iconsnode scripts/build_icons.mjsRegenerate app icons from source art.
pnpm typecheckpnpm -r typecheckTypecheck every workspace package.
pnpm linteslint .Lint the whole repo.
pnpm formatprettier --write .Format the whole repo.

Troubleshooting

  • Vite proxy ECONNRESET / ECONNREFUSED, or the backend aborts with OPENSSL_Uplink ... no OPENSSL_Applink (Windows). A MinGW libcrypto on PATH (e.g. C:\msys64\mingw64\bin) can get loaded for TLS and crash the worker. backend/__init__.py strips MinGW dirs from the process PATH at import, so the standard commands above work regardless of your shell PATH.
  • Port :8000 stays bound after Ctrl-C (Windows). pnpm dev tree-kills the backend on exit, but a manually started uv run uvicorn --reload can orphan a worker — kill the whole process tree if a stale one holds the port.
  • Backend stuck in a restart loop. Almost always the reload watcher seeing its own log writes. Use the standard commands above (--reload-dir backend --reload-exclude "logs/*", already set in scripts/dev.mjs/dev-backend.ps1) rather than a bare uvicorn --reload with no scoping — that watches the whole repo root, including logs/backend.log.
  • Desktop first build seems stuck. It's compiling Rust; give it a few minutes.

For how to verify a change in the running app, see the running-the-app workflow.