imn@dev:~/oss/larder$ cat scheme.md
pwa client
optimistic mutations · offline queue
always-on next.js process
railway · not serverless on purpose
postgres
one active cart line per product — a db constraint
// planned deploy: one always-on Railway process · Postgres plugin · $5-10/month
imn@dev:~/oss/larder$ cat services.md
- Railway
- the planned host — one always-on next.js process plus a postgres plugin; not serverless, since sse and a live LISTEN die on a cold start.
- OpenAI
- planned for vision parsing of recipe screenshots, icon picking, and the assistant's tool calls — every call metered into a cost column.
- FireCrawl
- planned as the last step of the recipe-import cascade, reached only when a url exposes neither json-ld nor microdata.
- UploadThing
- planned storage for dish photos and recipe screenshots, compressed client-side to roughly 300kb before upload.
- Resend
- planned for magic-link auth and household invite links; needs a verified custom domain before launch.
- CodeRabbit
- already live: automated review on every pull request, with every thread resolved or explicitly rejected with reasoning before merge.
- GitHub Actions
- already live: a ci gate written to pass docs-only prs until package.json exists, plus a docs-to-wiki sync on every merge to main.
imn@dev:~/oss/larder$ cat stack.md
imn@dev:~/oss/larder$ cat highlights.md
- CONSTRAINT
- the core rule — one active cart line per product — is a postgres partial unique index (WHERE trip_id IS NULL), not an application check. duplicates are structurally impossible rather than merely discouraged.
- REALTIME
- sse over postgres listen/notify on a dedicated, non-pooled connection that re-listens after any drop. notify payloads are not persisted, so a reconnect just invalidates the household cache instead of replaying missed events.
- IMPORT
- the recipe cascade (json-ld → microdata → firecrawl → ai normalization) was validated against real bookmarked recipes and costed to roughly a cent each before any app code existed. instagram links skip straight to a screenshot prompt, since firecrawl cannot pass the login wall.
- OFFLINE
- the mutation queue persists to indexeddb rather than memory, specifically because ios pwas have no background sync api; conflicts resolve last-write-wins per row, which is safe for checkbox-shaped state.
- BUDGET
- every ai call is metered into a cost column from the very first ai feature, and the monthly cap throttles only the chat assistant — recipe import and icon picking keep working after it is hit.
- PLAN
- the build itself is model-routed: every row of the 8-phase plan is tagged fable, opus or sonnet, the board is a checked-in markdown file updated inside the same pr that does the work, and branch protection has been on since the first commit.