Pico is a production-style runtime validation application built with Vix.cpp.
Website: https://pico.vixcpp.com Runtime: Vix.cpp Purpose: validate Vix.cpp modules inside one real C++ backend application
Pico is not a framework and it is not a separate runtime. It is a real backend application used to verify that Vix.cpp modules work together under a practical application shape.
It connects HTTP routing, middleware, static files, durable KV storage, SQLite events, ThreadPool jobs, WebSocket runtime behavior, runtime metrics, time utilities, filesystem utilities, and Rix CSV export.
Vix.cpp modules should not only compile independently. They should also work together inside a running application with shared configuration, lifecycle, routing, persistence, observability, and diagnostics.
Pico exists for that purpose.
It is intentionally small, but it is not a toy example. It is structured like a real backend application:
HTTP app
-> middleware
-> routes
-> controllers
-> application services
-> infrastructure wrappers
-> Vix KV
-> SQLite
-> ThreadPool
-> WebSocket
-> runtime dashboardPico is used as a production-oriented integration target for Vix.cpp.
Pico currently exercises:
vix::App- HTTP routing
- middleware
- public static files
.envconfiguration- SQLite persistence
- durable KV storage
- runtime metrics
vix/timevix/fs- ThreadPool jobs
- WebSocket runtime
- Vix AttachedRuntime
- Rix CSV export
- browser-based runtime dashboard
cd pico
cp .env.example .env
vix devOpen:
http://127.0.0.1:8080
http://127.0.0.1:8080/status.htmlCheck the API:
curl http://127.0.0.1:8080/api
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/api/health
curl http://127.0.0.1:8080/api/statusPico includes a browser dashboard:
/status.htmlThe dashboard observes and tests:
- application health
- uptime
- boot count
- HTTP request count
- latest heartbeat
- WebSocket message count
- SQLite event count
- ThreadPool metrics
- KV write/read behavior
- background job execution
- WebSocket ping/pong behavior
- CSV export of runtime events
The dashboard is served from public/ through the Vix static file handler.
include/pico/
app/
AppBootstrap.hpp
application/
services/
EventService.hpp
JobService.hpp
RuntimeStatusService.hpp
domain/
models/
Event.hpp
infrastructure/
database/
DatabaseProvider.hpp
EventRepository.hpp
kv/
PicoKvStore.hpp
threadpool/
PicoThreadPool.hpp
websocket/
PicoWebSocketServer.hpp
presentation/
controllers/
EventController.hpp
HealthController.hpp
HomeController.hpp
JobController.hpp
KvController.hpp
StatusController.hpp
WebSocketController.hpp
middleware/
MiddlewareRegistry.hpp
routes/
RouteRegistry.hpp
support/
HttpResponses.hpp
JsonHelpers.hpp
src/
main.cpp
pico/
app/
AppBootstrap.cpp
application/
services/
EventService.cpp
JobService.cpp
RuntimeStatusService.cpp
domain/
models/
Event.cpp
infrastructure/
database/
DatabaseProvider.cpp
EventRepository.cpp
kv/
PicoKvStore.cpp
threadpool/
PicoThreadPool.cpp
websocket/
PicoWebSocketServer.cpp
presentation/
controllers/
EventController.cpp
HealthController.cpp
HomeController.cpp
JobController.cpp
KvController.cpp
StatusController.cpp
WebSocketController.cpp
middleware/
MiddlewareRegistry.cpp
routes/
RouteRegistry.cpp
support/
HttpResponses.cpp
JsonHelpers.cpp
migrations/
2026_06_08_000000_create_events.up.sql
2026_06_08_000000_create_events.down.sql
public/
index.html
status.html
app.css
app.js
storage/
.env.example
vix.app
vix.json
README.mdPico uses a layered backend structure.
domain
Pure application models.
application
Services that coordinate runtime behavior.
infrastructure
Vix-backed technical components such as SQLite, KV, ThreadPool, filesystem,
time, and WebSocket runtime.
presentation
HTTP controllers, middleware, and route registration.
app
Application bootstrap and dependency wiring.
support
Shared JSON and HTTP helpers.This keeps the runtime wiring explicit while avoiding a monolithic main.cpp.
main.cpp stays intentionally small:
#include <pico/app/AppBootstrap.hpp>
int main()
{
pico::app::AppBootstrap bootstrap;
return bootstrap.run();
}Application setup lives in:
pico::app::AppBootstrapAppBootstrap owns the startup sequence.
It creates and connects:
vix::config::Configvix::AppDatabaseProviderEventRepositoryPicoKvStorePicoThreadPoolEventServiceRuntimeStatusServiceJobServicePicoWebSocketServer- middleware
- routes
- static files
- templates
Startup flow:
main.cpp
-> AppBootstrap
-> load .env
-> create vix::App
-> open SQLite database
-> open durable KV store
-> create ThreadPool
-> initialize event schema
-> mark boot count
-> configure static files
-> configure optional compression
-> register middleware
-> register runtime metrics
-> register routes
-> run HTTP
-> optionally run HTTP + WebSocket togetherPico stores lightweight runtime state in Vix KV.
Current runtime counters include:
app/boot_count
app/last_heartbeat
http/requests
ws/messages
jobs/run_count
jobs/slow_run_countRuntimeStatusService exposes the current runtime snapshot through:
GET /api/statusExample response:
{
"ok": true,
"app": "pico",
"runtime": "vix.cpp",
"status": "running",
"uptime_seconds": 79,
"boot_count": 21,
"last_heartbeat": "2026-06-08T09:36:55Z",
"http_requests": 55,
"ws_messages": 6,
"job_runs": 4,
"slow_job_runs": 0,
"events": {
"total": 53
},
"threadpool": {
"running": true
}
}The heartbeat is updated through runtime middleware and formatted with vix/time.
Pico separates heartbeat state from heartbeat events.
heartbeat() updates the durable KV value only.
record_heartbeat_event() records a SQLite event when explicit event history is needed.
This avoids polluting the SQLite event table with one heartbeat event per HTTP request while still keeping the latest heartbeat visible in /api/status.
Pico uses Vix KV for diagnostic counters. Since these counters are operational state and not business data, a corrupted local KV store should not permanently prevent Pico from starting.
When the KV store fails to open because of corruption, Pico can move the corrupted store to a backup path and create a fresh KV store.
Expected behavior:
storage/kv
-> open fails because the KV log is corrupted
-> move to storage/kv.corrupted.<timestamp>
-> create fresh storage/kv
-> continue startupThis protects the runtime validation app from being blocked by local diagnostic-state corruption.
The SQLite database is separate:
storage/pico.dbKV recovery should not delete or modify the SQLite event database.
Pico stores runtime events in SQLite.
The event model contains:
id
source
type
payload
created_atCommon event types:
system / app.boot
kv / kv.write
kv / kv.delete
job / job.completed
job / job.slow.completed
ws / ws.open
ws / ws.ping
ws / ws.message
ws / ws.close
ws / ws.errorThe latest events are available through:
GET /api/eventsExample:
curl http://127.0.0.1:8080/api/eventsPico uses Rix CSV to export SQLite runtime events as CSV.
Rix is the optional userland library layer for Vix.cpp projects. It is separate from the Vix runtime and CLI, but belongs to the same ecosystem.
Vix.cpp provides the runtime, application workflow, and core modules.
Rix provides optional libraries that applications can add when needed.
In Pico:
Vix.cpp
-> HTTP runtime
-> middleware
-> KV
-> SQLite access
-> ThreadPool
-> WebSocket
-> time
-> filesystem
Rix
-> CSV export
Pico
-> real C++ backend using Vix.cpp + Rix CSVCSV export endpoint:
GET /api/events.csvExample:
curl -i http://127.0.0.1:8080/api/events.csvOr save it to a file:
curl -L http://127.0.0.1:8080/api/events.csv -o pico-events.csvThe endpoint returns:
Content-Type: text/csv; charset=utf-8
Content-Disposition: attachment; filename="pico-events.csv"Pico uses Vix KV to persist small runtime values.
Write a value:
curl -X POST http://127.0.0.1:8080/api/kv \
-H "Content-Type: application/json" \
-d '{"key":"demo","value":"hello"}'Read a value:
curl http://127.0.0.1:8080/api/kv/demoDelete a value:
curl -X DELETE http://127.0.0.1:8080/api/kv/demoThe status dashboard also performs a KV write/read test from the browser.
Pico uses the Vix ThreadPool through PicoThreadPool.
Run a diagnostic job:
curl -X POST http://127.0.0.1:8080/api/jobs \
-H "Content-Type: application/json" \
-d '{"name":"demo-job","value":21}'Run a slow timeout-observation job:
curl -X POST http://127.0.0.1:8080/api/jobs/slowThreadPool metrics are available through:
GET /api/threadpoolThe metrics include values such as:
workers
pending
active
idle_workers
busy_workers
submitted
completed
failed
cancelled
timed_out
rejectedPico can run HTTP and WebSocket together through Vix AttachedRuntime.
When WebSocket is enabled, Pico exposes a WebSocket runtime on the configured WebSocket port.
The status dashboard can test WebSocket behavior by sending a typed ping message and expecting a pong response.
Diagnostic routes:
GET /api/ws/info
GET /api/ws/metricsSupported WebSocket behavior includes:
- client open events
- raw echo messages
- typed
ping/pong - room join
- room broadcast
- close events
- error events
Routes are registered from:
src/pico/presentation/routes/RouteRegistry.cppCurrent routes:
GET /api
GET /health
GET /api/health
GET /api/status
GET /api/threadpool
POST /api/kv
GET /api/kv/:key
DELETE /api/kv/:key
GET /api/events
POST /api/events
GET /api/events.csv
POST /api/jobs
POST /api/jobs/slow
GET /api/ws/info
GET /api/ws/metricsThe / route is served from:
public/index.htmlThe status page is served from:
public/status.htmlMiddleware is registered from:
src/pico/presentation/middleware/MiddlewareRegistry.cppCurrent middleware includes:
- CORS for local development
- rate limiting for
/api - request logging
- security headers
- body size limits for write routes
- custom API headers
- runtime metrics middleware
Recommended middleware order:
CORS
-> rate limit
-> request logging
-> security headers
-> body limits
-> runtime metrics
-> routesStatic files live in:
public/The app mounts public/ at /.
Current public files:
public/index.html
public/status.html
public/app.css
public/app.jsThe frontend is intentionally framework-free. It uses plain HTML, CSS, and JavaScript to inspect the runtime through the HTTP and WebSocket APIs.
Start by copying the example environment file:
cp .env.example .envImportant local values:
APP_NAME=pico
APP_ENV=development
SERVER_PORT=8080
DATABASE_ENGINE=sqlite
DATABASE_SQLITE_PATH=storage/pico.db
VIX_ORM_DIR=migrations
WEBSOCKET_ENABLED=true
WEBSOCKET_PORT=9090Runtime values and secrets belong in:
.envDocumented expected variables belong in:
.env.examplePico uses two important Vix files:
vix.app
vix.jsonvix.app describes the application build manifest.
vix.json describes Vix orchestration and project metadata.
Rule:
vix.app -> application build manifest
vix.json -> Vix project/orchestration config
.env -> local runtime values and secretsVix generates an internal build project under:
.vix/generated/app/Do not edit generated files manually. Edit vix.app and source files instead.
Pico includes a migrations/ directory.
Current migration:
2026_06_08_000000_create_events.up.sql
2026_06_08_000000_create_events.down.sqlORM commands:
vix orm status
vix orm migrate
vix orm rollback --steps 1Pico also ensures the events table exists at startup through EventRepository::ensure_schema().
Templates can be placed in:
views/The app configures the template directory through:
app.templates(views_path);vix dev
vix build
vix run
vix testsFor stronger local validation:
vix check --tests --runHealth:
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/api/healthRuntime status:
curl http://127.0.0.1:8080/api/statusThreadPool metrics:
curl http://127.0.0.1:8080/api/threadpoolEvents:
curl http://127.0.0.1:8080/api/eventsCSV export:
curl -L http://127.0.0.1:8080/api/events.csv -o pico-events.csvKV write/read:
curl -X POST http://127.0.0.1:8080/api/kv \
-H "Content-Type: application/json" \
-d '{"key":"demo","value":"hello"}'
curl http://127.0.0.1:8080/api/kv/demoJob execution:
curl -X POST http://127.0.0.1:8080/api/jobs \
-H "Content-Type: application/json" \
-d '{"name":"demo-job","value":21}'WebSocket diagnostics:
curl http://127.0.0.1:8080/api/ws/info
curl http://127.0.0.1:8080/api/ws/metricsPico should remain small, but real.
It should not become a large framework example or a business application. Its purpose is to keep validating Vix.cpp runtime behavior under realistic conditions.
Keep these rules:
- keep
main.cppminimal - keep startup wiring in
AppBootstrap - register routes through
RouteRegistry - register middleware through
MiddlewareRegistry - keep HTTP logic inside controllers
- keep runtime coordination inside services
- keep database, KV, filesystem, time, ThreadPool, and WebSocket wrappers under
infrastructure - keep reusable JSON and HTTP helpers under
support - use Vix modules where they exist
- use Rix for optional userland libraries
- do not mix Rix into the Vix core runtime identity
For reviewers and contributors, the most important files are:
src/main.cpp
src/pico/app/AppBootstrap.cpp
src/pico/presentation/routes/RouteRegistry.cpp
src/pico/presentation/middleware/MiddlewareRegistry.cpp
src/pico/application/services/RuntimeStatusService.cpp
src/pico/infrastructure/kv/PicoKvStore.cpp
src/pico/infrastructure/database/EventRepository.cpp
src/pico/infrastructure/websocket/PicoWebSocketServer.cpp
public/status.html
public/app.jsThese files show the core runtime flow from process startup to browser-visible diagnostics.
Pico is the Vix.cpp runtime validation app.
It proves that a native C++ backend can be structured, observed, and exercised through Vix.cpp while remaining explicit and understandable.
It validates the runtime in a real application shape:
C++ source
-> Vix.cpp runtime
-> HTTP app
-> middleware
-> services
-> KV + SQLite
-> ThreadPool
-> WebSocket
-> runtime dashboard
-> Rix CSV exportPico should stay focused: small enough to understand, real enough to catch integration problems.