Scaffold the Go app: auth, migrations, bundle import

Bring up the stage 1 skeleton described in the PRD, enough that the app
builds, serves, and can be populated with dishes.

- net/http server with shared-password Basic auth, /healthz outside it,
  graceful shutdown, and TZ-aware calendar days
- SQLite via modernc (pure Go, static binary), opened with WAL and a single
  connection
- migration runner: numbered SQL files embedded and applied once each inside
  a transaction, recorded in schema_migrations
- bundle import (PRD §7.3) as a live feature on the Ruoat tab: paste JSON or
  upload a file, get a per-row Finnish report. The same importer is reachable
  as `foodster -import` for repopulating a scratch database
- templ views and hand-written CSS with light-dark() theming; the Datastar
  v1.0.3 client is vendored, since the Go SDK ships no browser asset and a
  CDN would break an offline LAN

Names are normalized to sentence case rather than title case: Finnish
capitalizes only the first word of a phrase, so "Keitetyt perunat" is right
and "Keitetyt Perunat" is not. PRD §6 and §7.3 are amended to match.

Testing is behind make targets rather than ad-hoc commands: `make check` runs
lint, unit tests and scripts/smoke.sh, which exercises auth, static assets
and every import path against a scratch database on a spare port.
This commit is contained in:
Esa Kataja
2026-09-05 18:15:17 +03:00
parent 6ed047aafd
commit c9a63bdd9e
17 changed files with 1503 additions and 12 deletions
+20 -2
View File
@@ -4,6 +4,10 @@ COMPOSE ?= podman compose
BIN := foodster
PKG := ./cmd/foodster
# Vendored Datastar client. Bump, run `make vendor`, commit the result.
DATASTAR_VERSION ?= v1.0.3
SEED ?= seeds/testi.json
# Registry coordinates, shared password and TZ live here. Gitignored.
ifneq (,$(wildcard .env))
include .env
@@ -14,7 +18,7 @@ endif
GOFILES = $(shell find . -name '*.go' -not -name '*_templ.go' 2>/dev/null)
.DEFAULT_GOAL := help
.PHONY: help generate build run test lint fix image push release up down logs clean
.PHONY: help generate build run seed test smoke check lint fix vendor image push release up down logs clean
help: ## Show this help
@grep -hE '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) \
@@ -32,9 +36,23 @@ run: generate ## Run locally on :8080
FOODSTER_DB=$${FOODSTER_DB:-./foodster.db} \
go run $(PKG)
test: generate ## Run tests
seed: ## Import a dish bundle (SEED=seeds/testi.json)
go run $(PKG) -import $(SEED)
test: generate ## Run unit tests
go test ./...
smoke: generate ## End-to-end check: auth, static assets, bundle import
./scripts/smoke.sh
check: lint test smoke ## Everything that must pass before a commit
@echo "check: all passed"
vendor: ## Re-download the Datastar client (DATASTAR_VERSION=v1.0.3)
curl -sSfL -o cmd/foodster/static/datastar.js \
"https://cdn.jsdelivr.net/gh/starfederation/datastar@$(DATASTAR_VERSION)/bundles/datastar.js"
@head -1 cmd/foodster/static/datastar.js
lint: ## go vet, gofmt check, golangci-lint when installed
go vet ./...
@bad=$$(gofmt -l $(GOFILES) 2>/dev/null); \