An observability playground. Press a button, watch the signal propagate through Prometheus, Loki, Grafana, and Sentry in real time.
| Tool | Version |
|---|---|
| Docker Desktop | 24+ |
| Docker Compose | v2.24+ |
| Node.js | 20+ (local dev only) |
# 1. Clone and enter the repo
git clone <repo-url> && cd signal-lab
# 2. Copy environment variables
cp .env.example .env
# 3. Start everything
docker compose up -d
# 4. Wait ~30 s for migrations to run, then verify
curl http://localhost:3001/api/health
Expected response:
{ "status": "ok", "info": { "database": { "status": "up" } } }
| Service | URL | Notes |
|---|---|---|
| Signal Lab UI | http://localhost:3000 | Main application |
| Backend API | http://localhost:3001/api | REST API |
| Swagger Docs | http://localhost:3001/api/docs | Interactive API docs |
| Prometheus | http://localhost:9090 | Raw metrics |
| Grafana | http://localhost:3100 | Dashboards |
| Loki (via Grafana) | http://localhost:3100/explore | Log explorer |
Complete this in under 5 minutes to confirm every signal is working.
open http://localhost:3000
You should see the Signal Lab home page with the gradient brand icon.
curl http://localhost:3001/metrics | grep scenario_runs_total
You should see counter lines like:
scenario_runs_total{type="success",status="completed"} 1
scenario_runs_total{type="system_error",status="failed"} 1
open http://localhost:3100
{app="signal-lab"} | jsonscenarioType, scenarioId, duration fieldssystem_error run with tag scenarioType: system_errorSENTRY_DSN set in .env){ "signal": 42, "message": "I'm a teapot" }metadata: { easter: true, signal: 42 }To populate the history list with sample runs:
docker compose exec backend npm run prisma:seed
docker compose down
# Remove volumes (wipes database and Grafana state)
docker compose down -v
# Backend
cd apps/backend
npm install
npm run prisma:migrate:dev
npm run start:dev
# Frontend (separate terminal)
cd apps/frontend
npm install
npm run dev
Requires a local PostgreSQL instance. Set DATABASE_URL in .env.
signal-lab/
├── apps/
│ ├── backend/ # NestJS API
│ └── frontend/ # Next.js 14 App Router
├── prisma/
│ ├── schema.prisma # Database schema
│ ├── migrations/ # SQL migrations
│ └── seed.ts # Sample data
├── infra/
│ ├── prometheus/ # Scrape config
│ ├── loki/ # Log aggregation config
│ ├── promtail/ # Log shipper config
│ └── grafana/ # Provisioned datasources + dashboard
├── .cursor/ # Cursor AI layer
│ ├── rules/ # Stack guardrails (5 files)
│ ├── skills/ # Custom skills (4 skills)
│ ├── commands/ # Workflow commands (3 commands)
│ ├── hooks/ # Automation hooks (2 hooks)
│ ├── mcp.json # Marketplace skills (7 skills)
│ └── AI-LAYER.md # AI layer documentation
└── docker-compose.yml # Full stack in one command
See .cursor/AI-LAYER.md for the full documentation.
Quick reference:
# Scaffold a new endpoint with observability
/add-endpoint <domain> <operation>
# Audit a service for observability completeness
/check-obs apps/backend/src/scenarios/scenarios.service.ts
# Run a PRD through the orchestrator pipeline
/run-prd prds/002_prd-observability-demo.md
| Layer | Technology |
|---|---|
| Frontend | Next.js 14, shadcn/ui, Tailwind CSS, TanStack Query, React Hook Form |
| Backend | NestJS 10, TypeScript strict |
| Database | PostgreSQL 16, Prisma ORM |
| Metrics | Prometheus, prom-client |
| Logs | Pino → Promtail → Loki |
| Errors | Sentry |
| Dashboards | Grafana (provisioned) |
| Infra | Docker Compose |