Skip to content
Tehran

ML · production

Pico

Café demand forecasting — tells a café what to prepare tomorrow.

Role
Sole developer
Year
2026
Kind
ML · production
Hosting
Own server, Tehran
Status
62 ms
http:// 45.159.150.193:8000
Pico: the live product

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.

  1. Sales ingestion that imports a café's history and keeps it current.
  2. Time-series forecasts of daily demand for every item on the menu.
  3. A dashboard that turns forecasts into concrete production and purchasing numbers for the day.
  4. Background jobs for imports and model runs, so the app stays responsive while they work.
  5. Deployment on my own server with Docker, Gunicorn and Nginx, plus a public demo account.

03 Screens

The live product.

01 / 05

04 Architecture

How Pico fits together.

  • Component
  • Worker pool
  • Request
Pico’s components, grouped left to right by layer: Client, Edge, App, Workers, Data.

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.

  1. 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.

  2. 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.

  3. 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

esc
Top of the page
Proof in numbers
Selected work
Also shipped
How I ship
Experience
Stack
Work with me
Pico — case study
ArchPan — case study
Garsha — case study
Fenderesky — case study
MirOffice — case study
Copy email address
Download CV
Open GitHub
Open LinkedIn
Open live demo: Pico
Open live demo: ArchPan
Open live demo: Garsha
Open live demo: Fenderesky
Open live demo: MirOffice