Architecture Overview
Norn is structured as three independent modules: an API server, a React UI, and a CLI. They communicate through a REST API and WebSocket connection.
System diagram
Module boundaries
API (api/)
The Go backend — a single binary that runs the HTTP server, WebSocket hub, deploy/forge pipelines, cron scheduler, and health checker.
api/
├── handler/ REST + WebSocket handlers (chi router)
├── hub/ WebSocket broadcast hub (gorilla/websocket)
├── k8s/ Kubernetes API client (client-go)
├── model/ infraspec parser, data models
├── pipeline/ Deploy, Forge, and Teardown pipelines
├── secrets/ SOPS encrypt/decrypt + K8s sync
├── cron/ Cron scheduler (in-container execution)
└── store/ PostgreSQL persistence (pgx)CLI (cli/)
Charm-powered terminal client. Connects to the API via HTTP and WebSocket.
cli/
├── api/ HTTP + WebSocket API client
├── cmd/ Cobra commands (status, deploy, logs, etc.)
├── style/ Lip Gloss color palette and component styles
└── terraform/ Terraform runner for cluster commandsUI (ui/)
React 19 + Vite + TypeScript single-page application.
ui/src/
├── components/ AppCard, LogViewer, DeployPanel, Welcome, StatusBar
├── hooks/ useApps, useWebSocket
└── types/ TypeScript interfacesRequest flow
A typical deploy request flows through the system like this:
API endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/health | Service health check |
| GET | /api/apps | List all discovered apps |
| GET | /api/apps/:id | App detail + recent deployments |
| GET | /api/apps/:id/logs | Stream pod logs |
| POST | /api/apps/:id/deploy | Trigger deploy pipeline |
| POST | /api/apps/:id/restart | Rolling restart |
| POST | /api/apps/:id/rollback | Rollback to previous image |
| GET | /api/apps/:id/artifacts | List retained image tags |
| GET | /api/apps/:id/secrets | List secret names |
| PUT | /api/apps/:id/secrets | Update secrets |
| GET | /api/apps/:id/snapshots | List DB snapshots |
| GET | /api/apps/:id/health-history | Health check history |
| POST | /api/apps/:id/forge | Trigger forge pipeline |
| DELETE | /api/apps/:id/forge | Trigger teardown pipeline |
| GET | /api/apps/:id/forge | Get forge state |
| GET | /api/deployments | List all deployments (filterable) |
| WS | /ws | Real-time events |
Configuration
| Variable | Default | Description |
|---|---|---|
NORN_PORT | 8800 | API server port |
NORN_DATABASE_URL | postgres://norn:norn@localhost:5432/norn_db?sslmode=disable | PostgreSQL connection |
NORN_APPS_DIR | ~/projects | Directory to scan for infraspec.yaml |
NORN_UI_DIR | (empty) | Path to built UI static files (production only) |
NORN_URL | http://localhost:8800 | CLI: API server URL |