Web UI for spark-vllm-docker — recipe management, deployment, and monitoring for DGX Spark
Project description
Spark Pulse
Web UI for spark-vllm-docker — recipe management, deployment, and monitoring for NVIDIA DGX Spark hardware.
License: MIT — Copyright © 2026 Kharkevich Engineering Lab
Disclaimer: This project is not sponsored by, endorsed by, or affiliated with NVIDIA Corporation or any of its subsidiaries. NVIDIA, DGX, and NVIDIA trademarks are property of their respective owners.
Features
- Recipe Browser — Browse available vLLM deployment recipes, view model details, configs, and mods
- Job Management — Launch deployments with custom parameters, monitor status, view live logs via SSE, stop jobs
- Memory Monitor — Real-time GPU memory, CPU RAM, and disk usage via SSE streaming
- Cache Manager — Browse and clean HF model cache, wheels, ccache, Triton cache, and more
- Settings — Configure spark-vllm-docker path, default container, GPU memory utilization
- OIDC Authentication — Configurable authentication (Keycloak, Auth0, Google, Azure AD, etc.)
- Dark/Light Theme — Switch between dark, light, or system theme (persisted in localStorage)
- Custom Modals — Beautiful confirmation dialogs and error alerts
- MCP Server — Expose spark-vllm-docker operations as Model Context Protocol tools for AI assistants
Architecture
┌─────────────┐ HTTP / SSE ┌──────────────────────┐
│ Browser │ ◄───────────────► │ FastAPI + Uvicorn │
│ React SPA │ │ Port 8100 │
└─────────────┘ │ │
│ spark-vllm-docker/ │
│ Docker, nvidia-smi │
└──────────────────────┘
Project Structure
spark-pulse/
├── pyproject.toml # Python package config (setuptools)
├── README.md
├── LICENSE
│
├── spark_pulse/ # Python package
│ ├── __init__.py # Package init + version
│ ├── app.py # FastAPI app factory (creates app, mounts SPA)
│ ├── cli.py # CLI: spark-pulse start|install|mcp|...
│ ├── config.py # Config loader (YAML + env vars)
│ ├── service.py # Systemd service management
│ ├── auth.py # OIDC authentication middleware + routes
│ ├── mcp_server.py # MCP (Model Context Protocol) server
│ ├── config.yaml # Default configuration
│ ├── routers/ # API route modules
│ │ ├── recipes.py # Recipe listing + detail
│ │ ├── deployments.py # Deployment CRUD + launch/stop
│ │ ├── memory.py # GPU/CPU/disk stats
│ │ ├── cache.py # Cache scanning + cleanup
│ │ └── settings.py # Settings CRUD
│ ├── tools/ # Tool abstractions (real/mock swap)
│ │ ├── __init__.py # Factory: real vs mock
│ │ ├── system.py # nvidia-smi, free, df
│ │ ├── cache.py # cache dir scanning
│ │ └── recipes.py # YAML recipe parsing
│ ├── mock/ # Simulation mode implementations
│ │ ├── system.py # DGX Spark 128GB mock
│ │ ├── cache.py # Plausible cache sizes
│ │ ├── recipes.py # 6 realistic recipes
│ │ └── deployments.py # In-memory tracker
│ ├── ui/ # Built frontend (generated by `npm run build`)
│ │ └── index.html # Vite build output
│ └── data/ # Persistent state (deployments.json)
│
├── web/ # Frontend (separate npm project)
│ ├── package.json # Vite + React + TypeScript + Tailwind
│ ├── vite.config.ts # Builds to ../spark_pulse/ui/
│ ├── tsconfig.json
│ └── src/
│ ├── main.tsx # Entry point
│ ├── App.tsx # Router + AuthProvider
│ ├── lib/
│ │ ├── types.ts # TypeScript types
│ │ ├── api.ts # API client + SSE hooks
│ │ ├── utils.ts # Formatting helpers
│ │ ├── theme.ts # Theme state manager
│ │ └── auth.ts # Auth context
│ ├── hooks/
│ │ └── useQuery.ts # Data fetching hook
│ ├── components/
│ │ ├── Layout.tsx # Sidebar nav + theme toggle
│ │ ├── StatusBadge.tsx # Status indicators
│ │ └── Modal.tsx # Confirm + Alert modals
│ └── pages/
│ ├── RecipesPage.tsx
│ ├── JobsPage.tsx
│ ├── MemoryPage.tsx
│ ├── CachePage.tsx
│ └── SettingsPage.tsx
│
└── scripts/
├── run-dev-server.sh # Full dev (venv + frontend + backend)
├── run-backend.sh # Backend only (simulation)
├── run-production.sh # Production mode
└── build-ui.sh # Build frontend only
Installation
As a Python package
From PyPI
# Install from PyPI
python3 -m pip install spark-pulse
# Optional MCP extras
python3 -m pip install "spark-pulse[mcp]"
If you install with user-site packages (python3 -m pip install --user spark-pulse),
ensure your local bin directory is in PATH:
export PATH="$HOME/.local/bin:$PATH"
From local source
# Install from local repo
pip install -e .
# Or with MCP support
pip install -e ".[mcp]"
This provides the spark-pulse CLI command.
First-time setup
# Install Python dependencies (from repo root)
pip install -e ".[dev]"
# Build frontend
cd web && npm install && npm run build && cd ..
# Configure (edit spark_pulse/config.yaml or use Settings page)
# Default spark_vllm_path: /tmp/spark-vllm-docker
Usage
Quick start (development)
# One command — venv + frontend deps + backend (sim) + frontend dev server
./scripts/run-dev-server.sh
# → Frontend: http://localhost:3000
# → Backend: http://localhost:8100 (+ /docs Swagger UI)
Simulation mode (local dev without DGX)
Set SIMULATION_MODE=1 to get mock data for all APIs — useful for frontend
development on macOS or any machine without a DGX Spark:
# Full dev (includes frontend dev server)
./scripts/run-dev-server.sh
# Backend only (simulation)
./scripts/run-backend.sh
# → http://localhost:8100
# Production mode (real tools, needs spark-vllm-docker + nvidia-smi)
./scripts/run-production.sh
# Just build frontend into spark_pulse/ui/
./scripts/build-ui.sh
Systemd service (production)
After installing from PyPI or source, register the service in one of these modes.
System scope (root-managed)
# Install and start system unit (requires sudo)
sudo spark-pulse install
# Start/stop/status
sudo spark-pulse start-service
sudo spark-pulse stop-service
spark-pulse status
# Unregister unit
sudo spark-pulse uninstall
User scope (no sudo)
# Install and start user unit
spark-pulse install --user
# Start/stop/status for user unit
spark-pulse start-service --user
spark-pulse stop-service --user
spark-pulse status --user
# Unregister user unit
spark-pulse uninstall --user
User-mode unit files are written under ~/.config/systemd/user/ and env files under
~/.config/spark-pulse/. System-mode files are written under /etc/systemd/system/
and /etc/.
To keep user services running after logout, enable lingering:
loginctl enable-linger "$USER"
MCP Server (AI Assistants)
Expose spark-vllm-docker operations as MCP tools:
# Start MCP server (stdio mode for AI assistants)
spark-pulse mcp
Exposed tools:
list_recipes— list available deployment recipesget_recipe— get recipe details by namecreate_deployment— launch a recipe deploymentstop_deployment— stop a running deploymentlist_deployments— list all deployments with statusget_memory— get GPU/CPU/disk statslist_cache— list cache directories with sizesclean_cache— clean specified cache directoriesget_logs— get deployment logs
OIDC Authentication
Configure authentication in spark_pulse/config.yaml:
auth_enabled: true
oidc_provider_url: https://keycloak.example.com/realms/myrealm
oidc_client_id: spark-manager
oidc_client_secret: your-secret-here
Or via environment variables:
export SPARK_PULSE_AUTH_ENABLED=true
When enabled:
- All routes are protected except
/health,/auth/* - Users are redirected to the OIDC provider on
/auth/login - After successful auth, users see their name and a logout button in the header
Environment variables
Override config via environment:
export SPARK_VLLM_PATH=/path/to/spark-vllm-docker
export WEBUI_PORT=8100
export SPARK_PULSE_AUTH_ENABLED=true
API Reference
| Method | Path | Description |
|---|---|---|
GET |
/api/recipes |
List all recipes |
GET |
/api/recipes/{id} |
Recipe details |
GET |
/api/deployments |
List deployments |
POST |
/api/deployments |
Create + launch |
DELETE |
/api/deployments/{id} |
Stop deployment |
GET |
/api/deployments/{id}/logs |
Recent logs |
GET |
/api/memory |
All memory stats |
GET |
/api/memory/gpu |
GPU stats |
GET |
/api/cache |
Cache dirs + sizes |
POST |
/api/cache/clean |
Clean caches |
GET |
/api/settings |
Current settings |
PUT |
/api/settings |
Update settings |
GET |
/auth/login |
Redirect to OIDC login |
GET |
/auth/callback |
OIDC callback |
GET |
/auth/me |
Current user info |
GET |
/ |
SPA entry point |
Building for distribution
# Build frontend
cd web && npm run build && cd ..
# Build Python package
python -m build
The built frontend is bundled into the wheel via package-data: ui/**/*.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spark_pulse-1.1.0.tar.gz.
File metadata
- Download URL: spark_pulse-1.1.0.tar.gz
- Upload date:
- Size: 123.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5d35ffb01264305675e5d524af8cfe94cbba018f7f7da3a16777b4ef47baa63
|
|
| MD5 |
f8a66fdddcf7333fe1ddf2bf8e7e30dc
|
|
| BLAKE2b-256 |
045b620b2ca9ac7b6399c5989b0d62cdccaa44cd21a65a4cb6720a5c119b5b21
|
Provenance
The following attestation bundles were made for spark_pulse-1.1.0.tar.gz:
Publisher:
release.yml on kharkevich-engineering-lab/spark-pulse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spark_pulse-1.1.0.tar.gz -
Subject digest:
a5d35ffb01264305675e5d524af8cfe94cbba018f7f7da3a16777b4ef47baa63 - Sigstore transparency entry: 1596381615
- Sigstore integration time:
-
Permalink:
kharkevich-engineering-lab/spark-pulse@e920bb368fc84cf7e3fa2ac1fa4a74c47c05f26e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/kharkevich-engineering-lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e920bb368fc84cf7e3fa2ac1fa4a74c47c05f26e -
Trigger Event:
push
-
Statement type:
File details
Details for the file spark_pulse-1.1.0-py3-none-any.whl.
File metadata
- Download URL: spark_pulse-1.1.0-py3-none-any.whl
- Upload date:
- Size: 124.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46675351816f822dada812427dce61d1b6c350ef9f5579ea962b1ff85cec9528
|
|
| MD5 |
7f2905bcec83421834a540485fa9bb5a
|
|
| BLAKE2b-256 |
ce431cb9e1a36992cf5e277490fbe8417c930fa59914cab7b064673692b1b410
|
Provenance
The following attestation bundles were made for spark_pulse-1.1.0-py3-none-any.whl:
Publisher:
release.yml on kharkevich-engineering-lab/spark-pulse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spark_pulse-1.1.0-py3-none-any.whl -
Subject digest:
46675351816f822dada812427dce61d1b6c350ef9f5579ea962b1ff85cec9528 - Sigstore transparency entry: 1596381709
- Sigstore integration time:
-
Permalink:
kharkevich-engineering-lab/spark-pulse@e920bb368fc84cf7e3fa2ac1fa4a74c47c05f26e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/kharkevich-engineering-lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e920bb368fc84cf7e3fa2ac1fa4a74c47c05f26e -
Trigger Event:
push
-
Statement type: