ML · production
Pico
Café demand forecasting — tells a café what to prepare tomorrow.
Stack
- Backend
- Django REST Celery Gunicorn
- Frontend
- React
- Data & ML
- PostgreSQL Redis pandas scikit-learn
- Infrastructure
- Docker Nginx
01 The problem
Every morning a café decides how much of each item to prepare and what to order, mostly from memory.
Guess high and food goes in the bin; guess low and the best sellers are gone by noon. The sales history that could answer the question already exists in the till, but nothing turns it into a decision.
02 What I built
Designed, built and run by one developer.
Demand forecasting for cafés and food businesses. It ingests sales, predicts daily demand per item as a time series, and turns the forecast into concrete production and purchasing decisions on a dashboard. Imports and model runs are Celery jobs behind a Django REST API; the front end is React. Served by Gunicorn behind Nginx, in Docker, on a server I run.
- Sales ingestion that imports a café's history and keeps it current.
- Time-series forecasts of daily demand for every item on the menu.
- A dashboard that turns forecasts into concrete production and purchasing numbers for the day.
- Background jobs for imports and model runs, so the app stays responsive while they work.
- Deployment on my own server with Docker, Gunicorn and Nginx, plus a public demo account.
03 Screens
The live product.
01 / 04
Sales history, with waste plotted against daily sales.
Live inventory, with batches close to expiry flagged.
Weekday patterns and best sellers — the signal the forecast learns from.

The same dashboard on a phone.
04 Architecture
How Pico fits together.
- Component
- Worker pool
- Request
Connections
- Browser to Nginx , HTTP
- Nginx to React dashboard , static
- Nginx to Django REST · Gunicorn , /api
- Django REST · Gunicorn to PostgreSQL , reads · writes
- Django REST · Gunicorn to Redis , enqueue
- Redis to Celery workers , jobs
- Celery workers to pandas · scikit-learn , fit · predict
- Celery workers to PostgreSQL , forecasts
05 Key decisions
What I chose, why, and what it cost.
-
Decision
Classical ML with pandas and scikit-learn, not deep learning
Why
Each café has a modest amount of history with strong weekly patterns. Engineered features on a classical model train quickly on a CPU-only VPS and are easy to reason about when a forecast looks wrong.
Trade-off
A lower ceiling on unusual patterns, and feature engineering is manual work that has to be revisited as new kinds of data arrive.
-
Decision
Imports and model runs as Celery jobs, never inside a request
Why
Importing history and refitting models take longer than any HTTP request should. Queuing them keeps the API fast and lets failed runs retry on their own.
Trade-off
Redis and a worker process to operate, and the interface has to show job state instead of a simple spinner.
-
Decision
Show what to make and buy, not a chart of predictions
Why
The people using it run a café, not a data team. A number next to each item is something they can act on before opening.
Trade-off
Less raw detail on screen for anyone who wants to inspect the model; that view has to be asked for.
06 Try it yourself
Pico is running. Go and use it.
Demo login · click to copy