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:
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"mains": [
|
||||
{"name": "Uunilohi", "categories": ["fish"], "has_sides": true},
|
||||
{"name": "Lasagnette", "categories": ["meat"], "has_sides": false},
|
||||
{"name": "Jauhelihakastike", "categories": ["meat"], "has_sides": true},
|
||||
{"name": "Risotto", "categories": ["vegetarian"], "has_sides": false},
|
||||
{"name": "Pakastepizza", "categories": ["meat"], "has_sides": false},
|
||||
{"name": "Kanakeitto", "categories": ["chicken"], "has_sides": false},
|
||||
{"name": "Kasvissosekeitto", "categories": ["vegetarian"], "has_sides": false}
|
||||
],
|
||||
"sides": [
|
||||
{"name": "Keitetyt perunat"},
|
||||
{"name": "Ranskalaiset"},
|
||||
{"name": "Muussi"},
|
||||
{"name": "Riisi"},
|
||||
{"name": "Pasta"}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"mains": [
|
||||
{"name": "Lihapullat", "categories": ["meat"], "has_sides": true},
|
||||
{"name": "Jauhelihakastike", "categories": ["meat"], "has_sides": true},
|
||||
{"name": "Makaronilaatikko", "categories": ["meat"], "has_sides": false},
|
||||
{"name": "Kaalilaatikko", "categories": ["meat"], "has_sides": false},
|
||||
{"name": "Uunimakkara", "categories": ["meat"], "has_sides": true},
|
||||
{"name": "Kanacurry", "categories": ["chicken"], "has_sides": true},
|
||||
{"name": "Broilerikastike", "categories": ["chicken"], "has_sides": true},
|
||||
{"name": "Kanawokki", "categories": ["chicken"], "has_sides": true},
|
||||
{"name": "Lohikeitto", "categories": ["fish"], "has_sides": true},
|
||||
{"name": "Uunilohi", "categories": ["fish"], "has_sides": true},
|
||||
{"name": "Kalapuikot", "categories": ["fish"], "has_sides": true},
|
||||
{"name": "Kasvispyörykät", "categories": ["vegetarian"], "has_sides": true},
|
||||
{"name": "Hernekeitto", "categories": ["vegetarian"], "has_sides": false},
|
||||
{"name": "Kasviscurry", "categories": ["vegetarian"], "has_sides": true},
|
||||
{"name": "Tortillat", "categories": ["meat", "chicken", "fish", "vegetarian"], "has_sides": false},
|
||||
{"name": "Kotipizza", "categories": ["meat", "chicken", "vegetarian"], "has_sides": false}
|
||||
],
|
||||
"sides": [
|
||||
{"name": "Perunamuusi"},
|
||||
{"name": "Riisi"},
|
||||
{"name": "Keitetyt perunat"},
|
||||
{"name": "Vihersalaatti"},
|
||||
{"name": "Höyrytetyt porkkanat"},
|
||||
{"name": "Ruisleipä"}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user