Watchman is a full-stack dashboard for monitoring self-hosted services from one place. It combines a React + TypeScript frontend with a Node.js + Fastify backend and supports real-time status visibility across your stack.
Important
Monitoring-only by design
Watchman is intentionally read-only. It does not start/stop/restart/reconfigure services.
If you run multiple services, Watchman gives you one dashboard instead of 10+ browser tabs.
| You need... | Watchman gives you... |
|---|---|
| Fast visibility across services | Unified health + stats endpoints and cards in a single UI |
| Support for multiple instances of a service | Numbered env-based multi-instance support (e.g. multiple qBittorrent/Synology instances) |
| Live status updates | WebSocket-based real-time updates |
| A trusted-network security model | Origin allow-list (CORS + WebSocket), service secrets encrypted at rest, PII-redacted logs — no auth/CSRF/rate-limiting by design (single-user) |
| Extensibility | Factory-driven service integration architecture |
- ✅ Unified dashboard for self-hosted service health and statistics
- ✅ Monitoring-only architecture (no service control plane)
- ✅ Multi-instance support for selected integrations
- ✅ Real-time updates via WebSockets
- ✅ OpenAPI 3.1 spec (
apps/backend/openapi.yaml) — no Swagger UI is served - ✅ Circuit breaker + caching patterns for resilient service polling
- ✅ Trusted-network security model — origin allow-list, encrypted secrets at rest, PII-redacted logging
Watchman supports 14+ service types. You can enable only what you use.
| Category | Integrations |
|---|---|
| Network & Security | AdGuard Home, Tor, Router (Beryl, Telenet) |
| Cryptocurrency | Bitcoin, Alby Hub |
| Storage & Sharing | qBittorrent, IPFS, Synology |
| Smart Home & Media | Homebridge, Philips Hue, Roon |
| Infrastructure | Mac Mini, Raspberry Pi |
| Social | Nostrcheck |
See full docs: docs/integrations/index.md
| Layer | Stack | Responsibility |
|---|---|---|
| Frontend | React 18, TypeScript, Vite, Tailwind CSS, TanStack Query | Dashboard UI, server state (React Query), live updates |
| Backend | Node.js, Fastify 5, WebSocket (ws), DuckDB, OpenAPI |
Service polling, REST + WebSocket API, config store |
| Monorepo | npm workspaces | Shared development workflow for frontend/backend |
The install.sh script sets up everything from scratch — Homebrew, Node.js, workspace dependencies, and a .app launcher:
git clone https://github.com/EraPartner/Watchman.git
cd Watchman
./install.shAfter installation, double-click the Launch Watchman.command shortcut or run:
npm run electron:prodOn first launch you'll need
apps/backend/.env.localpopulated. The installer prints a copy hint if it's missing.
git clone https://github.com/EraPartner/Watchman.git
cd Watchman
npm install
cp apps/backend/.env.example apps/backend/.env.local # set WATCHMAN_MASTER_KEY
npm run build
npm run start| Service | URL |
|---|---|
| Frontend (preview) | http://localhost:4173 |
| Backend API | http://localhost:3001 |
git clone https://github.com/EraPartner/Watchman.git
cd Watchman
npm install
cp apps/backend/.env.example apps/backend/.env.local
npm run dev| Service | URL |
|---|---|
| Frontend | http://localhost:5173 |
| Backend API | http://localhost:3001 |
| Variable | Why it matters |
|---|---|
WATCHMAN_MASTER_KEY |
Encrypts stored service secrets at rest — required in practice |
CORS_ALLOWED_ORIGINS |
Extra browser origins to allow (needed for non-loopback web access) |
BACKEND_V2_PORT / BACKEND_V2_HOST |
Bind address — optional (defaults 3001 / 0.0.0.0) |
Service connection details (hosts, tokens, etc.) are not env vars — they live
in the DuckDB config store, managed via the /config API or the UI. Full surface:
docs/reference/environment-variables.md.
# Development
npm run dev # frontend + backend in watch mode (concurrent)
npm run dev:frontend # frontend only
npm run dev:backend # backend only
npm run backend # alias of dev:backend
# Building
npm run build # production build (backend + frontend)
npm run build:frontend # frontend production build
npm run build:backend # backend production build
npm run build:dev # dev-mode frontend build
npm run preview # preview production frontend build
npm run dist # build backend + frontend, then package Electron .app
npm run clean # remove all node_modules / dist / out folders
# Production self-host
npm run start # backend + frontend preview (concurrent)
npm run start:backend # backend only
npm run start:frontend # frontend preview only
# Linting
npm run lint # frontend ESLint
npm run lint:frontend # frontend ESLint (explicit alias)
npm run lint:backend # backend ESLint
npm run lint:fix # autofix across workspaces
npm run format # Prettier across workspaces
npm run format:check # Prettier check across workspaces
npm run typecheck # tsc across backend + frontend
# Testing
npm run test # backend Vitest suite
npm run test:frontend # frontend Vitest suite
npm run test:all # backend + frontend (concurrent)
npm run test:coverage # frontend coverage report
npm run test:watch # backend watch mode
npm run test:e2e # Playwright e2e suite
npm run test:e2e:visual # Playwright with snapshot updates
# Electron (desktop app)
npm run electron:dev # desktop dev mode (NODE_ENV=development)
npm run electron:prod # desktop production mode (built backend + frontend)
npm run electron:clean # clean install, rebuild, launch
# Types
npm run generate:types # regenerate TypeScript types from openapi.yamlWatchman/
├── apps/
│ ├── frontend/ # React + TypeScript + Vite app (Playwright e2e in tests/)
│ ├── backend/ # Node.js + Fastify API + WebSocket
│ └── desktop/ # Electron desktop wrapper
├── docs/ # Knowledge base and project documentation
├── packaging/ # Electron release / packaging assets
├── scripts/ # Repo maintenance scripts (git hooks, …)
└── tools/ # Development and maintenance tooling
packages/*is a reserved npm-workspace glob for future shared packages; no shared packages exist yet.
- OpenAPI 3.1 spec:
apps/backend/openapi.yaml— documentation only; no Swagger UI is served. - Security model: single user on a trusted network — no authentication, CSRF, or rate limiting, by design (ADR-017 / ADR-025). Anyone who can reach the port can read and reconfigure, so do not expose the backend beyond your trusted network.
- Browser cross-origin access is gated by an origin allow-list shared by CORS and the WebSocket upgrade: desktop
watchman://, loopback, and anything inCORS_ALLOWED_ORIGINS. - Service secrets are encrypted at rest in the DuckDB config store (
WATCHMAN_MASTER_KEY); secrets and PII are never logged.
See SECURITY.md for the full threat model and how to report a vulnerability.
Read more:
| Topic | Link |
|---|---|
| Getting Started | docs/getting-started.md |
| Setup Guide | docs/guides/setup.md |
| Common Tasks | docs/common-tasks.md |
| Architecture | docs/architecture/index.md |
| Integrations | docs/integrations/index.md |
| Environment Variables | docs/reference/environment-variables.md |
| Troubleshooting | docs/troubleshooting.md |
| Contributing | docs/guides/contributing.md |
Contributions are welcome.
- Fork the repository
- Create a focused feature/fix branch
- Add/update tests and docs with your changes
- Run lint/build/test locally
- Open a pull request with clear context
Contribution guide: CONTRIBUTING.md · Security policy: SECURITY.md
This project is licensed under AGPL-3.0-only.
See LICENSE for details.