DEV Community

Cover image for ShopCast: a sales forecast a small shop can actually pay for
Jerrie Adah
Jerrie Adah

Posted on

ShopCast: a sales forecast a small shop can actually pay for

Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle Submission πŸ’Έ

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle

What I Built

The shop owner already knows Saturday is busy. What they cannot price is how much busier, or what happens if they run a Friday promo, or whether last month's "slow Wednesday" was just Wednesday.

Closed forecasting tools want a seat licence in dollars and the whole sales history on a server they control. For a bakery or mini-mart, that is not a product. That is a cost centre.

ShopCast is the version I would actually charge for. Export daily sales as a CSV (date, sales, optional promo). Click Start forecast. You get:

  • the next 1–8 weeks of sales, with a range, not a single smug number
  • unusual days the model did not expect (generator died, surprise catering order)
  • a backtest against the owner's own rule: "same as last week"
  • a chat box that answers "what if I promo every Friday?" with TabPFN's numbers, then Gemma's words

Who pays: a shop that would spend a few thousand naira a month to stop over-baking on Tuesdays.

welcome screen with Start forecast
welcome screen

Demo

video:

live app (Render): https://shopcast.onrender.com Note that a free Render box sleeps, so the first load can take a minute.

forecast chart: β€”
forecast chart

blue history, orange dashed future.

Unusual days table:
unusual days

Ask ShopCast answering a promo or forecast question, with Numbers behind this answer open.

Askshopcast

Code

GitHub logo AdahJerrie / shopcast

The shop owner uploads a sales CSV. The TabPFN API predicts next month's sales and flags unusual days, and Gemma explains the results in plain English.

ShopCast

Sales forecasts for small shops. Upload a daily sales CSV and ShopCast:

  • forecasts the next 1 to 8 weeks with TabPFN (Prior Labs' tabular foundation model), with a 10-90% band
  • flags unusual days (spikes and drops) by scoring each day with a model that never saw it
  • backtests itself on the last 28 days against "same as last week", so the owner can see whether to trust it
  • answers questions in plain English through a small Gemma agent: forecast, unusual days, and "what if I run a promo every Friday?"

CSV format

column required notes
date yes also accepts day, sale_date, transaction_date
sales yes also accepts revenue, amount, total, turnover; multiple rows per day are summed
promo no 1 on promo days; enables the what-if tool

At least 8 weeks of history is needed. Missing days are treated as zero sales. sample_data/lagos_bakery.csv is…

The files that matter:

  • shopcast/forecast.py β€” TabPFN, one week per call, walk forward
  • shopcast/anomaly.py β€” score each day with a model that never saw it
  • shopcast/agent.py β€” tools, keyword routing, "copy the naira exactly"
  • app.py β€” upload, preview, Start forecast, then the dashboard

How I Built It

I built this on a five-year-old Latitude: 2-core i5, 8 GB RAM, no usable GPU. About a gigabyte free on a good day. So the first design decision was boring and correct: do not run TabPFN or a 27B model on this laptop. TabPFN goes through Prior Labs. Gemma goes through Google AI Studio. The laptop runs Streamlit and pandas.

The second decision was how to make forecasting tabular. Each day is a row: weekday, payday window, Nigerian public holidays, festive season, promo flag, sales from 7 and 14 days ago. Lags start at 7 on purpose. That way TabPFN predicts a whole week in one call, then those predictions become next week's lags. Four API calls for 28 days, not 28.

Unusual days use the same model in 5-fold out-of-sample scoring. I first flagged on robust z-score alone and the sample bakery lit up like a Christmas tree β€” 13 "anomalies" on ordinary noise. So a day now has to be statistically weird and at least 25% off expected. On the planted sample, TabPFN then flagged exactly the four days I had sabotaged.

Then the chat started lying.

Failure 1: Gemma 3 was gone. First Ask ShopCast reply on the real key:

404 NOT_FOUND … models/gemma-3-27b-it is not found

I had copied a model name from last week's docs. ListModels on this key returned two Gemma 4 models. Switched to gemma-4-26b-a4b-it. One environment variable. That is the open-weight pitch in practice: the product did not die with the model card.

Failure 2: the 1B model cannot route. I tried local gemma3:1b because the laptop can just about hold it. It answered "what if I run a Friday promo?" by calling forecast for 14 days. Clear questions now skip the model: promo / strange / next week go straight to the tool. Gemma only routes the vague ones. Routing went from 1/3 to 4/4.

Failure 3: JSON ate the naira. json.dumps escaped ₦1,452,027 as \u20a61,452,027. Gemma read the trailing 6 and told the owner they would sell "61,452,027 dollars." ensure_ascii=False, and every answer now has a Numbers behind this answer panel. Trust the table, not the prose.

Failure 4: it ran before anyone asked. First version analysed the sample CSV the moment the page loaded β€” minutes of TabPFN on a shop owner's first click. Now: upload (or sample toggle) β†’ local preview of the last 10 days β†’ Start forecast. Change the file or the horizon and it waits again.

I also tried to use the Gemma 4 E2B I already had in Ollama (4.3 GB). After "closing heavy apps" I still had 0.9 GB free. Cursor, VS Code, Edge, Chrome, and Notion were sitting on the rest. We skipped it. Hosted Gemma stays the default. That is not ideology. That is an 8 GB machine.

Measured, on the sample bakery, real TabPFN + Gemma 4:

Check Result
TabPFN average daily error ₦4,671
"Same as last week" ₦11,248
Error vs naive 58.5% lower
Unusual days on planted sample 4 of 4

Why Does Open Innovation Matter?

  • The model vanished and the app did not. Gemma 3 27B 404'd. I listed what the key actually serves and swapped. A closed "forecasting API" with one SKU does not let you do that on a Sunday afternoon.
  • Small data is the product, not the edge case. A bakery has hundreds of daily rows, not millions. TabPFN is built for that. Asking a general LLM to "look at the CSV and predict October" is how you get confident fiction.
  • Cost stays at shop scale. TabPFN's free non-commercial tier plus Gemma on AI Studio is the difference between "₦2,000/month might work" and "the API bill is the business." Offline, Gemma 3 1B still explains a cached forecast on this laptop.
  • The owner's file is not a training set I keep. Preview and Start are local. The hosted path sends features to TabPFN and a short tool result to Gemma, not a dump of every receipt line.

My Agent Session

Building ShopCast: TabPFN forecasts and a Gemma agent that stopped inventing naira
You

Go through the Hacktoberfest Week 2 prompt, then give 3 to 5 project options that fit this laptop. Avoid anything too memory-draining.

Agent

The laptop is a Latitude 7480: 2-core i5-7300U, 8 GB RAM, Intel HD 620, about 1 GB free. Local models bigger than ~1B will thrash. I recommended ShopCast: a small-shop sales forecaster. TabPFN via Prior Labs API does the numbers. Hosted Gemma explains them. Optional Ollama fallback for offline chat.

You

Implement ShopCast as specified. Do not edit the plan file.

Agent

Scaffolded the Streamlit app, TabPFN week-by-week forecast, residual anomaly check, 28-day backtest vs same-weekday-last-week, and a Gemma agent with forecast / anomalies / what-if tools.

You

I already have gemma4:e2b-it-qat locally. Can that serve instead of gemma3:1b?

Agent

Yes, ShopCast reads OLLAMA_MODEL. Gemma 4 E2B is 4.3 GB. Only 0.9 GB RAM was free, so loading it would swap hard. Hosted Gemma stays the default.

You

Ask ShopCast returned 404 NOT_FOUND for models/gemma-3-27b-it.

Agent

Listed models on the key. Only gemma-4-26b-a4b-it and gemma-4-31b-it accept generateContent. Switched the default. Live TabPFN + Gemma 4 test: MAE ₦4,671 vs naive ₦11,248 (58.5% lower). Flagged the 4 planted unusual days.

You

It starts processing the moment ShopCast launches. I need to upload a real shop CSV, then click Start before it runs.

Agent

Welcome screen now. File is checked locally first (days, date range, promo column, last 10 rows). Start forecast is disabled until there is data. Changing the file or horizon waits for another click.

Prize Categories

  • Best Use of TabPFN β€” TabPFN 3.5 is the forecast, the anomaly scores, and the promo what-if, inside a small prediction agent
  • Best Use of Gemma β€” Gemma 4 26B hosted (after Gemma 3 404'd); optional Gemma 3 1B locally
  • Best Use of Render β€” render.yaml web service. ** https://shopcast.onrender.com **
  • Best Use of Entire β€” agent session above

Top comments (0)