# Foodster A self-hosted dinner log and meal suggester for a single household. Record what the family actually ate, and — later — let the app propose seven dinners drawn from that history. The interface is in Finnish. The code, comments and documentation are in English. See [PRD.md](PRD.md) for the full specification. ## Status **Stage 1 — eating history: in development.** The meal catalog and the daily log come first, because the suggester is worthless until there are a few weeks of real history to weight against. Stage 2 — the seven-meal suggester — starts once that history exists. ## Stack One static Go binary. No Node.js, no bundler, no separate database server. | | | |---|---| | Language | Go 1.27 | | HTTP | stdlib `net/http` + `http.ServeMux` | | Views | [templ](https://templ.guide), server-rendered | | Interactivity | [Datastar](https://data-star.dev) — signals and DOM patching in one ~11 kB script | | Styling | hand-written CSS, `light-dark()` for themes | | Database | SQLite via `modernc.org/sqlite` (pure Go) | | Auth | HTTP Basic, one shared household password | | Runtime image | `FROM scratch` | ## Quick start ```sh cp .env.example .env # then edit it make run # http://localhost:8080 ``` `make` on its own lists every target: ``` make fix gofmt, templ fmt, go mod tidy make lint go vet, gofmt check, golangci-lint when installed make test go test ./... make build ./foodster make image build and tag vYYYYMMDD-N (creates a git tag) make push push the newest tag and :latest make release image + push make up/down/logs compose ``` ## Configuration Everything is environment variables. `.env` is gitignored; start from `.env.example`. | Variable | Default | Purpose | |---|---|---| | `FOODSTER_PASSWORD` | *required* | Shared password. The app will not start without it. | | `FOODSTER_DB` | `/data/foodster.db` | SQLite file path. | | `TZ` | `Europe/Helsinki` | Used for every calendar-day calculation. | | `FOODSTER_REPO` | *required to build* | Image repository, no tag. | | `FOODSTER_TAG` | `latest` | Tag to run under compose. | | `FOODSTER_PORT` | `8080` | Host port to publish. | Set `TZ` in development too. Under UTC the date rolls over three hours late, which is exactly when dinner gets logged. ## Deployment Images are built with Podman and run under Docker Compose on a LAN server. They are OCI images, so either engine works. ```sh make release # build, tag, push # on the server: docker compose pull && docker compose up -d ``` Versions are CalVer — `vYYYYMMDD-N`, where `N` is the Nth build that day. The running version is served at `GET /healthz`, which is the one route outside authentication. There is no database container. SQLite lives on a named volume, so a backup is a file copy. ## Security Access is a single shared password over HTTP Basic — no accounts, no sessions. Credentials are compared in constant time, but Basic auth sends them in cleartext, so this belongs on a private LAN. Put TLS in front of it before exposing it anywhere else. ## Mockups `mockups/` holds standalone HTML design studies. Open them directly in a browser; they are references, not part of the build. ## License [MIT](LICENSE).