edea83228cd7ee0bc5b32fd4ecf5d665c3c5cc34
The store keeps a Menu Set's state in the directory layout (drafts/ versus published/) and its metadata in a manifest, with publishing as a single directory rename. Editing is allowed on Drafts only, so a published menu can never change under a customer. Stages 2 and 3 of docs/plan.md, with tests.
menu-admin
Uploads, orders and publishes the customer-facing menus of a restaurant Site as
photographed Pages, replacing the scp-a-JPG workflow. One instance per Site;
docs/plan.md is the agreed design and CONTEXT.md is the glossary.
Status
Built so far: Site config parsing, the Menu Set store and the image pipeline, with tests. Not yet built: the public renderer, the admin, the container and the Ansible role.
Layout
src/config.ts Site config: brand, theme, Sections, limits
src/storage/manifest.ts Manifest type, validation, atomic JSON writes
src/storage/sets.ts The Menu Set store: create, add Pages, publish, restore, delete
src/storage/validate.ts Boot validation: fatal problems and warnings
src/images/pipeline.ts sharp variants: Original, Viewing image, Thumbnail
test/ node:test suites
docs/plan.md The agreed plan
docs/adr/ Decisions worth remembering
Working on it
Node 24 or newer runs the TypeScript sources directly.
npm install
npm test # node:test
npm run typecheck # tsc --noEmit
Storage model
data/
├── originals/<section>/<set-id>/<page-id>.<hash>.<ext> # kept, never served
├── drafts/<section>/<set-id>/ # manifest.json + variants
└── published/<section>/<slug>/ # manifest.json + variants
The directory decides a Menu Set's state; the manifest carries metadata only.
<slug> is the valid-until date, else the publication date. The Current Menu
Set for a Section is the published one with the newest publishedAt. Published
sets are immutable: changing a menu means publishing a new set.
Languages
TypeScript
81%
JavaScript
6.5%
CSS
6.2%
Shell
4.5%
Jinja
0.7%
Other
1.1%