Nebluna Analytics
Demand forecasting system for coffee shops that turns a daily sales CSV into a 30-day forecast with confidence intervals, served by a Prophet + FastAPI backend on GCP Cloud Run.
End-to-end time series forecasting platform: a Prophet model wrapped in a FastAPI service, containerized with Docker and deployed to Google Cloud Run, plus a Streamlit dashboard where a shop owner uploads sales history and gets predictions, confidence bands, and model error metrics.

Gallery
Project Overview
Nebluna Analytics forecasts daily demand for coffee shops. You upload a CSV of historical sales, pick a horizon between 7 and 90 days, and get a forecast with a 95% confidence band plus the model’s error metrics. It is a Prophet model served by a FastAPI service on GCP Cloud Run, with a Streamlit dashboard on top.
Technical Implementation
Model Layer
DataProcessor handles loading, validation and cleaning: it enforces the date / sales contract, requires at least 30 days of history, and normalizes the frame into Prophet’s expected shape. DemandForecaster wraps the model, fitting it, holding out the tail of the series for evaluation, and generating future dates with 95% confidence bounds. Prophet decomposes the series into trend plus multiplicative weekly and yearly seasonality, so the day-of-week effect stays separate from the slower annual drift.
API Layer
A FastAPI service exposes four endpoints:
GET /health: liveness check for Cloud RunPOST /api/v1/upload: accepts a CSV, trains the model, returns fit metricsPOST /api/v1/forecast: generates n days ahead, optionally with confidence intervalsGET /api/v1/stats: summary statistics for the loaded dataset
Requests and responses are typed with Pydantic, so the OpenAPI documentation is generated from the same definitions the service validates against. A custom exception hierarchy returns a useful message on a malformed CSV instead of a stack trace.
Evaluation
The model is scored on a held-out tail of the series rather than on the data it was fit to. Three metrics are surfaced in the dashboard: MAE, the average error in currency, which is the number to size an order against; MAPE, the same error as a percentage, comparable across shops of different sizes; and RMSE, which penalizes large misses more heavily and catches a model that is usually fine but occasionally very wrong.
Dashboard
A Streamlit app consumes the API and organizes the output into three tabs, Historical, Forecast and Metrics, with interactive Plotly charts. The sidebar carries the CSV upload, a 7 to 90 day horizon slider and a toggle for confidence intervals.
Deployment
The API is containerized and runs on GCP Cloud Run, built for both arm64 and amd64 so the same image works on an Apple Silicon laptop and on Google’s infrastructure. Cloud Build handles CI/CD from cloudbuild.yaml, and a budget alert caps monthly spend. Prophet sits on NumPy and Pandas C extensions that break when conda and pip packages mix in one environment, so the boundary is fixed by rule: conda for local development, pip wheels inside the Docker image.
Testing
pytest covers the data processing pipeline and the API endpoints: validation failures, malformed input and the happy path.
The Challenge
- Coffee shop sales carry strong weekly seasonality plus a slower annual trend, and a naive average washes both out
- A forecast without an error estimate is not actionable for someone ordering stock
- The model had to be usable by a shop owner, not only from a notebook
- Prophet's dependency chain (NumPy/Pandas C extensions) breaks easily between local development and Linux containers
The Approach
- Prophet handles multiplicative weekly and yearly seasonality directly, so the trend and the day-of-week effect stay separated
- Every prediction ships with a 95% confidence band, and the model is scored on a held-out tail of the series
- A Streamlit dashboard fronts the API: upload a CSV, pick a horizon, read the chart
- Conda for local development and pip wheels inside Docker, with the boundary documented so the environments never get mixed
Results
- Live on two platforms: Streamlit Cloud for the dashboard, GCP Cloud Run for the API
- Four REST endpoints with auto-generated OpenAPI docs and Pydantic-validated payloads
- MAE, MAPE and RMSE surfaced in the UI, computed on a held-out tail of the series
- Multi-platform Docker build (arm64 + amd64) with Cloud Build CI/CD and a $10/month budget alert
Impact
A shop owner uploads a sales CSV and gets a demand forecast with its error margin, from a browser and without writing code.
Project Details
Objective
Give small coffee shops a demand forecast they can operate from a browser, with the model served behind a REST API rather than living in a notebook.
Theme
Applied time series forecasting for small-business inventory planning.
Date
August 3, 2026