Purchasing coffee-bean ordering-rhythm tool - roast days, resting window, and daily usage in; an ordering calendar and freshness-expiry warnings out
Please build me a single-file HTML coffee-bean ordering
rhythm tool for a coffee shop. It opens straight in the
browser, no network, no dependencies, data stored
locally only.
Put this background in the tool's intro: coffee beans
run on two clocks - a long shelf life and a short
freshness window, and freshly roasted beans need a few
days of resting before they extract stably. A wrong
ordering cadence fails both ways: order too early and
the beans are past their peak by the time you open them
(stale but "not expired"); order too late and un-rested
beans hit the grinder - sharp, sour, hard to extract.
The tool aligns the order date, the arrival date, and
the freshness window.
Data it takes in:
1. Usage rhythm: average daily bean usage (g) per
coffee in play - enter directly, or derive from
"dose per cup 【】g × daily cups"
2. Supplier info, per coffee: fixed roast days (e.g.
Tuesdays/Fridays), order-to-arrival days, bag size
【】g, minimum order quantity
3. Freshness window (the shop's own numbers, editable
per coffee): usable from day 【】 after roast
(resting minimum), quality declines from day 【】
(freshness ceiling), use-within 【】 days after
opening
4. Current stock: per coffee, unopened bags (each bag's
roast date) and opened bags (opening date)
Core behavior:
- Freshness expiry calendar: each unopened bag expires
on "roast date + freshness ceiling"; opened bags run
a separate line on "opening date + use-within" - the
two lines display separately and whichever expires
first warns first, going yellow 【3】 days ahead
- Order suggestions: back-calculate the "must order by"
date from usage (leaving room for the resting minimum
and transit), with a suggested quantity (rounded to
bag size, at least the minimum order)
- Arrival-age check: for the suggested order date,
compute the arrival date, that batch's roast date,
its age on arrival, and the date it becomes usable -
if "usable date" falls after "stock runs out," flag
red: the gap can only be bridged by transferring
stock or temporarily substituting a coffee
- Two separate red flags: stock that can't be finished
inside its freshness window = overhang (spoilage
risk); usable date that doesn't connect = gap
(stockout risk) - counted separately because the
fixes point in opposite directions
Output: an ordering calendar blocked by coffee (this
week through the week after next) - each block showing
current stock in days-of-coverage terms, suggested
order/arrival/usable dates, suggested quantity, and
red/yellow warnings with a one-line reason.
Constraints (for the coding agent):
- Resting days, freshness bounds, and the opened-bag
window come only from user input - no "industry
default" values anywhere in the tool; every roaster
and brew method disagrees on these numbers, and
pre-filling them is a landmine
- Single file, localStorage persistence, print-friendly;
no accounts, no login, no cloud sync
Why it is written this way
Ordering beans is not a "how many days of stock are left" question - it's "how old will the beans be on arrival": the same bag arriving Monday vs Friday differs by half a freshness window. The tool moves the decision from stock counts onto a calendar; what the buyer sees is no longer "five bags left" but "when this stock runs out, the next batch is just entering its usable window." Once dates align, quantity is arithmetic.
The explicit ban on built-in resting defaults is where tools like this most often fail: light vs dark roast, espresso vs brew bar, and each roaster's advice differ wildly, and any "default seven days" gets copied as authority by some shop. Numbers must be entered per shop, per coffee, editable - the tool only does calendar math. This one constraint is what protects the tool's credibility; an extra keystroke is a fair price.
The opened-bag window running on its own line, separate from the roast date, is the dark corner most shops miss: opening accelerates the freshness clock (surface exposure jumps), so beans can be "well within shelf life" and long past tasting right. Two lines, whichever expires first warns first - otherwise the calendar looks tidy while the bar pours stale coffee.
Gap and overhang stay separate because their fixes point opposite ways: a gap calls for ordering earlier or transferring stock, an overhang for ordering less or switching to smaller bags - merged into one "anomaly" count, both get ignored. And unlike milk, beans can't be corrected tomorrow: roast cycle plus resting window means a mismatch takes two to three weeks to unwind, which is the entire reason this tool exists - to make the mismatch visible on a calendar weeks before it bites.
Variables
| Variable | Notes |
|---|---|
| Dose per cup | Standard dose in g from your recipe card; converts cups into bean usage |
| Resting minimum and freshness ceiling | Days after roast when beans become usable, and when quality starts declining - your numbers, agreed with your roaster, editable per coffee |
| Opened-bag use-within | Days to finish a bag after opening, the shop's own rule, tracked separately from the roast date |
| Bag size and minimum order | The roaster's bag weight and MOQ; drives the rounding rules for suggested quantities |
| Warning lead time | Days before expiry that a flag goes yellow - the handling window |