Track: Theme Track – Rethinking Waste
The waste problem and how we'd measure success
Every evening, small bakeries decide how much to bake the next morning, usually by rule of thumb ("last weeks' sales plus a safety margin"). Fresh bread cannot be stored, so whatever is unsold at closing time is thrown away, sold off cheaply or donated: food, flour, energy and money wasted every single day. Breadcast targets this daily over-production. We measure success with two weekly numbers: the waste rate (unsold items ÷ baked items) and the sold-out rate (share of days a product ran out before closing). Breadcast succeeds if, over four weeks, the waste rate falls with no higher sold-out rate and no lower margin than the four weeks before. The app's backtest applies exactly this measurement to past data: on a synthetic 14-month bakery history, it cuts unsold items by about 40% (waste rate 17% → 11%), with about 1% fewer units sold and a slightly higher margin.
What it does
- Load sales history: a CSV with
date, product, baked, sold, plus optional rain, temperature and holiday. A synthetic sample bakery is built in. Nothing is uploaded; everything runs in the browser. - Set what an item is worth: price, baking cost and value if unsold. A slider adds an extra cost of waste (environmental and social) per wasted item.
- Train & backtest: one machine-learning model per product is trained in under a second. It replays the last 8 weeks it has never seen and compares its recommendations with what was actually baked.
- Tomorrow's bake plan: one number per product, a 25–90% demand range, last week for comparison and the main drivers of each forecast. Toggle rain or holidays, then print or export for the morning shift.
How we built it (the ML)
- Censored quantile regression: per product, a linear model on
log(1 + sales)with weekday, seasonality (sine/cosine of day of year), holiday and day-before-holiday flags, rain, temperature and lagged sales (last four same weekdays, last 7 days). It is trained from scratch in JavaScript with Adam on the pinball loss, with L2 regularisation and standardised features. - Sell-outs are censored observations: when everything was sold, true demand was higher than sales. Those days only penalise under-prediction, so the model does not learn that "sold out" means "low demand", a classic trap that makes naive forecasts bake less and less. A unit test shows the censoring-aware model recovers true demand where a naive one underestimates it.
- Newsvendor decision: the forecast quantile equals the critical ratio
(price − cost) / (price − value if unsold + waste penalty). Making waste more expensive lowers the target quantile and the batch size, so the bakery sees the waste-versus-sell-out trade-off openly. - Conservative evaluation: on sold-out days true demand is unknown, so we assume demand = sales. This can only understate Breadcast's benefit.
- Explainability: a per-forecast breakdown shows which features push tomorrow's number up or down.
- Plain JavaScript ES modules and SVG with no dependencies or server. 8 automated tests (Node test runner). Developed with the help of Anthropic's Claude as an AI coding assistant. The demo video uses synthetic text-to-speech narration.
Challenges
Censored demand was the hardest part: historical "sold" numbers are not demand. Designing an honest backtest that never credits the model with sales it cannot prove was the second.
What's next
- A pilot with a real bakery: weekly waste-rate and sold-out-rate tracking against the previous four weeks.
- Automatic weather forecasts and regional holiday calendars.
- Pooled models across products and stores for new items with little history, and rolling-origin backtests.
Limitations
The sample bakery is synthetic. Its "actually baked" column follows a rule of thumb (average of the last four same weekdays plus 20%). Results on real data will differ. The model is linear by design: explainable and fast, but simpler than gradient boosting.
Built With
- css3
- html5
- javascript
- machine-learning
- quantile-regression
- svg
Log in or sign up for Devpost to join the conversation.