Skip to content

Getting started ​

This guide takes a fresh clone to a running stack with a seeded database and a passing test suite.

Prerequisites ​

ToolVersionNotes
Go1.27+API, worker, scheduler, and the cmd/ operator tools
Node.js24.22 (LTS)Frontend, marketing site, and this docs site
pnpm12corepack enable && corepack prepare [email protected] --activate
DockercurrentCompose v2 (docker compose)
golang-migratecurrentbrew install golang-migrate
sqlc1.31+brew install sqlc
golangci-lint2.xbrew install golangci-lint
aircurrentOptional hot reload: go install github.com/cosmtrek/air@latest

make check-tools reports which of these are missing.

Clone and configure ​

bash
git clone https://github.com/ovahol/ovahol.git
cd ovahol
cp .env.example .env

.env.example documents every variable. For local development the defaults are enough; the values worth knowing are covered in Running in production.

Run the stack ​

bash
make dev

This starts the backend containers through Docker Compose:

ServiceWhat it is
backendGin API with hot reload (air)
schedulerHourly jobs: subscription lifecycle, PM reminders, threshold alerts, webhook retention
workerAsynchronous work
valkeyCache, sessions, rate limits, security counters
psql_ovPostgreSQL 17, published on host port 5434

The frontend is not part of that stack. In a second terminal:

bash
make dev-frontend
EndpointURL
APIhttp://localhost:8080
Apphttp://localhost:5173
PostgreSQLlocalhost:5434 (user/password/db from .env)
HealthGET /health
MetricsGET /metrics (see operations)

make dev-backend brings up the same services explicitly (backend scheduler worker valkey psql_ov), and make dev-watch runs the API on the host with air instead of in a container.

Database ​

Migrations live in backend/repository/migrations/ and are applied with:

bash
make migrate          # apply everything pending
make migrate-status   # current version
make migrate-down     # roll back one
make reset-db         # drop, recreate, migrate, and re-seed

Migrations run automatically when the API container starts; make migrate is for a database you already have running. Tenant schemas are not in this directory — see multi-tenancy.

Seeding inserts lookup data (device types, roles, plan rows, failure codes) and the super admin from SUPER_ADMIN_EMAIL / SUPER_ADMIN_PASSWORD:

bash
make seed

The dev database is reachable straight from the host:

bash
psql postgres://oaedward:password1234@localhost:5434/ovahol_dev

Tests ​

bash
make test-unit         # go test -short, no database
make test-integration  # -tags=integration
make test-e2e-local    # boots a temporary PostgreSQL and runs tests/e2e
make test              # full suite in the compose test environment

The e2e suite shares one database and one seeded catalog across tests, so a fresh database is required between full runs. test-e2e-local creates its own temporary cluster; when pointing at an existing server, create a throwaway database per run instead of reusing ovahol_dev.

Frontend checks:

bash
cd frontend
pnpm type-check
pnpm test
pnpm lint
pnpm lint:tokens   # forbids hardcoded slate/white palette classes
pnpm build

Code generation ​

Two generators, both checked in:

bash
make sqlc             # shared-schema queries -> module repository packages
make openapi-generate # openapi.yaml -> Go + TypeScript clients
make docs-api         # openapi.yaml -> docs/api/reference.md

If you change a query under backend/repository/queries/, run make sqlc. If you add or change a route, run make openapi-generate. Generated files are committed, and CI fails when they drift from their source.

Tenant-schema queries are not generated: they are hand-written .sql files embedded with //go:embed and loaded per request. See multi-tenancy.

Repository map ​

backend/    Go API, worker, scheduler, operator commands, migrations
frontend/   Vue 3 application (Vite, Pinia, Tailwind)
web/        Marketing site (Vue 3)
docs/       This documentation site (VitePress)
api/        openapi.yaml — the API contract
scripts/    One-off data and inventory tooling

Where next ​

Ovahol developer documentation