A fork of mtelver's day10 project
day10-web: Status Dashboard Design#
Date: 2026-02-04 Status: Approved Author: Brainstorming session
Overview#
A web frontend for day10 that allows package maintainers to check their package status and operators to monitor system health. It runs as a separate service that reads day10's output directories.
Audience#
- Package maintainers - Want to see if their packages are building/documented correctly, investigate failures
- day10 operators/admins - Monitoring system health, viewing logs, managing runs
Not intended as a general documentation browser (that's what the generated HTML at /docs/ is for).
Architecture#
┌─────────────┐ writes ┌──────────────────────────┐
│ day10 │ ───────────────►│ /data/ │
│ (batch) │ │ ├── cache/logs/ │
└─────────────┘ │ │ ├── runs/ │
│ │ │ └── summary.json│
│ │ └── latest │
│ └── html/ │
┌─────────────┐ reads │ └── p/{pkg}/{ver}/ │
│ day10-web │ ◄───────────────┤ │
│ (Dream) │ └──────────────────────────┘
└─────────────┘
│
▼
HTTP :8080
Key properties:
- No database - all state derived from filesystem
- Read-only access to day10's directories
- Single configuration: paths to cache-dir and html-dir
- Lightweight:
day10-web --cache-dir /data/cache --html-dir /data/html
Pages and Routes#
Dashboard (/)#
- Overview cards: total packages, build success rate, doc success rate
- Latest run summary (timestamp, duration, pass/fail counts)
- Link to full run history
Package List (/packages)#
- Searchable/filterable table of all packages
- Columns: package name, version, build status, doc status, last updated
- Click through to package detail
Package Detail (/packages/{name}/{version})#
- Build status with link to build log
- Doc status with link to doc log and generated docs
- Dependencies tab: what this package depends on (with their statuses)
- Reverse dependencies tab: what depends on this package
- Solver solution: OCaml version, full dependency list with versions
Run History (/runs)#
- List of all batch runs (timestamp, duration, success/fail counts)
- Click through to run detail
Run Detail (/runs/{run-id})#
- Full summary.json data displayed nicely
- List of failures with links to logs
- Filterable list of all packages processed in that run
Data Sources#
All data is read from the filesystem:
Run data ({cache-dir}/logs/)#
| Path | Provides |
|---|---|
runs/ directory listing |
Run history |
runs/{id}/summary.json |
Run statistics, failure list |
runs/{id}/build/*.log |
Build logs |
runs/{id}/docs/*.log |
Doc generation logs |
latest symlink |
Most recent run |
Package data ({cache-dir}/{platform}/)#
| Path | Provides |
|---|---|
solutions/ |
Cached solver results (deps, OCaml version) |
build-*/layer.json |
Build metadata and status |
doc-*/layer.json |
Doc generation metadata and status |
Generated docs ({html-dir}/)#
| Path | Provides |
|---|---|
p/{pkg}/{ver}/ existence |
Doc generation succeeded |
| Direct links | Link to generated documentation |
Dependency graph#
- Built from solutions data
- Forward deps: parse the solution for a package
- Reverse deps: scan all solutions (indexed on startup)
UI Approach#
Rendering: Server-side HTML with minimal JS#
Dream renders HTML directly using its built-in HTML DSL or Tyxml. No heavy frontend framework:
- HTML pages rendered on server
- Small amount of vanilla JS for search/filtering
- CSS styling (Pico CSS or simple custom styles)
Why this approach#
- Simpler to build and maintain
- No frontend build pipeline
- Fast initial page loads
- Works without JavaScript for core functionality
- Fits "operational dashboard" use case
Visual style#
- Clean, functional dashboard aesthetic
- Status badges: green (success), red (failed), yellow (skipped)
- Sortable tables for package lists
- Collapsible sections for dependency trees
- Syntax highlighting for logs (highlight.js)
Log viewer#
- Display logs inline with scrolling
- Link to raw log file for download
- Client-side search within log
Project Structure#
/workspace/
├── day10.opam # Existing - the batch runner
├── day10-web.opam # New - the web frontend
├── bin/
│ └── main.ml # Existing day10 CLI
├── lib/ # Existing day10_lib
├── web/
│ ├── dune
│ ├── main.ml # day10-web entry point
│ ├── server.ml # Dream routes and handlers
│ ├── views/
│ │ ├── layout.ml # Common HTML layout
│ │ ├── dashboard.ml # Dashboard page
│ │ ├── packages.ml # Package list and detail pages
│ │ └── runs.ml # Run history and detail pages
│ ├── data/
│ │ ├── run_data.ml # Read summary.json, logs
│ │ ├── package_data.ml # Read solutions, layer metadata
│ │ └── deps.ml # Dependency graph builder
│ └── static/
│ ├── style.css
│ └── app.js # Minimal JS for search/filter
└── dune-project # Update to add day10-web package
Shared code: day10-web depends on day10_lib to reuse types (e.g., Run_log.summary).
CLI and Configuration#
day10-web [OPTIONS]
Required:
--cache-dir DIR Path to day10's cache directory
--html-dir DIR Path to generated documentation
Optional:
--port PORT HTTP port (default: 8080)
--host HOST Bind address (default: 127.0.0.1)
--platform PLATFORM Platform subdirectory (default: debian-12-x86_64)
Example usage#
# Development
day10-web --cache-dir /data/cache --html-dir /data/html
# Production (bind to all interfaces)
day10-web --cache-dir /data/cache --html-dir /data/html \
--host 0.0.0.0 --port 80
Deployment with nginx#
server {
listen 80;
server_name docs.example.com;
# Status dashboard
location / {
proxy_pass http://127.0.0.1:8080;
}
# Generated documentation
location /docs/ {
alias /data/html/;
autoindex on;
}
}
Error Handling#
Missing data#
| Condition | Behavior |
|---|---|
| No runs yet | Dashboard shows "No runs recorded" |
| Package not found | 404 with search suggestions |
| Run ID not found | 404 with link to run history |
| Log file missing | "Log not available" (may be GC'd) |
| Malformed JSON | Log warning, show partial data |
Large data sets#
| Data | Strategy |
|---|---|
| Package list | Paginated (50/page) with search |
| Run history | Paginated (20/page), most recent first |
| Dependency tree | Depth-limited (2 levels), click to expand |
| Reverse deps | Count with paginated list |
Concurrent access#
- Read-only filesystem access is safe
- Atomic swaps mean readers see consistent state
- No locking needed
Startup#
- Validate cache-dir and html-dir exist
- Build reverse dependency index
- Log startup time and index size
Out of Scope (YAGNI)#
- Real-time updates / WebSockets
- Authentication / access control
- Write operations (triggering builds)
- REST API (just HTML pages for now)
Dependencies#
New opam dependencies for day10-web:
dream- Web frameworktyxmlor Dream's HTML DSL - HTML generation
Implementation Plan#
- Set up project structure (dune-project, day10-web.opam, web/ directory)
- Implement data layer (run_data.ml, package_data.ml, deps.ml)
- Implement views (layout, dashboard, packages, runs)
- Wire up Dream routes in server.ml
- Add static assets (CSS, minimal JS)
- Add CLI with cmdliner
- Update admin guide with deployment instructions
- Write tests for data layer