Skip to content
brorn
No. 021 · Other apps

nutri.me

App that closes a household's weekly food loop: a menu, a priced shopping list, a cart at the online supermarket, cooking day and printed labels for the portions.

Live
Period
2026-08 → now
Platforms
Web · Bluetooth label printer
Role
Solo: design, build, ship
Tech
Fig. 1 · Week menu
Fig. 2 · Shopping list
Fig. 3 · Recipe card

§1The problem

Planning the week, shopping, batch cooking and knowing what's in the freezer were separate chores. There was no single flow from the menu to the label with the expiry date.

§2What I built

  • Five screensWeek, Coach, Kitchen, Shopping and Pantry.
  • CoachBuilds a menu from rules set on screen, using an LLM and recipes fetched live from a recipe service.
  • ShoppingPriced shopping list, with the cart handed to the online supermarket (the final purchase is made there).
  • RecipesCreated in the recipe service through the page's own API (each write checked afterwards by reading it back).
  • LabelsOne label per portion on a Bluetooth printer, via D-Bus, with freeze and expiry dates.
  • PantryPortion states (planned, bought, cooked, frozen).
  • Local access guardAgainst requests from other sites.

§3The hard parts

5 entries
  1. 01

    Automating services with no public API

    A script-driven browser, and discovering that the page uses a REST API (GET/PATCH) instead of simulating typing.

  2. 02

    Bluetooth printer on Linux without root

    The standard library wouldn't connect; I wrote only the transport, talking to BlueZ over D-Bus, and reused the library's protocol.

  3. 03

    A printer that falls asleep

    And a page confirmation that never arrives (solved by polling the state).

  4. 04

    Readable labels

    Registering the font manually so the canvas doesn't render boxes, and checking without wasting labels (PNG-only mode).

  5. 05

    Slow asynchronous jobs and calendar rules

    It always plans next week, never the current one.

§4Result

The full cycle is implemented and was rehearsed end to end in August 2026, with label printing confirmed on the printer. Last updated in October 2026.

§5Stack

  • Next.js 16
  • TypeScript
  • SQLite (better-sqlite3)
  • LLM via command line (JSON output)
  • Puppeteer / automated browser
  • Bluetooth LE (BlueZ / D-Bus, niimbluelib)
  • @napi-rs/canvas
  • pm2
  • Tailscale