DEV Community

Pranjal Manhgaye
Pranjal Manhgaye

Posted on AI-assisted

PLOT 🌿 - TabPFN on Real Frost Data Tells You to Touch Grass

Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass Submission 🌿

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass 🌿


πŸ’‘ The idea in one breath

Most weather apps keep you scrolling. PLOT does the opposite. πŸ“΅βž‘οΈπŸŒ±

You pick a place (or share your location πŸ“). Real weather loads 🌦️. TabPFN, an open tabular foundation model 🧠, reads your day like a row in a frost table and answers:

⏸️ Wait · 🚢 Walk · 🌿 Garden

Then it hands you three concrete steps and expects you to leave. The screen's job is under a minute. ⏱️


πŸ› οΈ What I Built

Field Value
🌿 Product PLOT - outdoor action signal + checklist
🧠 Brain TabPFN (tabpfn-client)
πŸ“Š Training data 30,684 real daily rows, 12 US cities, 2018-2024
🌦️ Weather Open-Meteo ERA5 reanalysis + live forecast
☁️ Hosting Render free tier
⚑ Stack FastAPI, static UI, no chat layer

πŸ‘₯ Who it's for: anyone with a yard, balcony, or park nearby who overthinks the forecast and under-leaves the house.


🎬 Demo

πŸŽ₯ Screen recording: [https://www.youtube.com/watch?v=0zisIS7GLjg]

πŸ”— Try it yourself: plot-touch-grass.onrender.com

⏳ First load on Render free tier may take ~30s while the service wakes up.

πŸ“Έ Screenshots

πŸ”οΈ Hero - PLOT landing page

🌦️ Live weather - Open-Meteo fills the form

🎯 TabPFN signal - wait / walk / garden with confidence

βš™οΈ How it works (60 seconds)

flowchart LR
    subgraph YOU["You"]
        A["Pick city or use location"]
    end

    subgraph DATA["Open-Meteo"]
        B["Today's temps, rain, wind, soil"]
        C["92-day frost window"]
    end

    subgraph AI["TabPFN"]
        D["Classify: wait, walk, garden"]
        E["Class probabilities"]
    end

    subgraph OUT["Outside"]
        F["3-step checklist"]
        G["Phone down"]
    end

    A --> B
    A --> C
    B --> D
    C --> D
    D --> E
    E --> F
    F --> G

πŸ—ΊοΈ User journey

sequenceDiagram
    participant U as User
    participant UI as PLOT UI
    participant OM as Open-Meteo
    participant T as TabPFN
    participant Y as Your yard

    U->>UI: Open site / pick Portland
    UI->>OM: GET /api/weather
    OM-->>UI: Real temps, frost lag, soil
    U->>UI: Get outdoor signal
    UI->>T: POST /api/check
    T-->>UI: garden, 83% confidence
    UI-->>U: Checklist (3 steps)
    U->>Y: Goes outside

πŸ—οΈ Architecture

graph TB
    subgraph Client["Browser"]
        WEB["Static UI / web"]
    end

    subgraph RenderHost["Render - plot-touch-grass"]
        API["FastAPI / backend/main.py"]
        ENG["OutdoorEngine / TabPFNClassifier"]
        CSV[("outdoor_history.csv - 30684 ERA5 rows")]
        WX["weather.py - Open-Meteo + fallback"]
    end

    subgraph External["Open services"]
        OM["Open-Meteo API"]
        TP["Prior Labs TabPFN"]
    end

    WEB -->|/api/weather| API
    WEB -->|/api/check| API
    API --> WX
    WX --> OM
    API --> ENG
    ENG --> CSV
    ENG --> TP

πŸ“ˆ The data story (real, not synthetic)

This is the part I cared about most. No fake temperatures. βœ…

flowchart TD
    A["Open-Meteo Historical API - ERA5"] --> B["scripts/fetch_real_data.py"]
    B --> C["12 cities x 7 years of daily rows"]
    C --> D["Feature engineering"]
    D --> D1["days_since_last_frost from min temp at 0C"]
    D --> D2["soil_moisture, wind, daylight"]
    D --> E["Labels via backend/labels.py"]
    E --> F["outdoor_history.csv - 30684 rows"]
    F --> G["TabPFN fit and predict"]

🌎 Cities in the training set

City Climate Rows
🌲 Portland, OR Cool marine ~2,557
🌧️ Seattle, WA Marine west coast ~2,557
πŸ™οΈ Chicago, IL Continental ~2,557
❄️ Minneapolis, MN Upper Midwest ~2,557
⛰️ Denver, CO High plains ~2,557
πŸ—½ New York, NY Humid subtropical ~2,557
🦞 Boston, MA Coastal temperate ~2,557
🌳 Atlanta, GA Warm humid ~2,557
🀠 Austin, TX Warm ~2,557
β˜€οΈ Phoenix, AZ Desert ~2,557
🌴 Miami, FL Tropical humid ~2,557
🌊 Los Angeles, CA Mediterranean ~2,557

πŸ“Š Label distribution (on real weather)

Action Meaning Share
🚢 walk Good to be outside, not a planting day ~57%
⏸️ wait Frost risk or bad conditions, prep indoors ~30%
🌿 garden Frost window + workable soil, hands in dirt ~13%

Labels come from transparent horticulture heuristics in backend/labels.py (frost-free days, precip, wind bounds). TabPFN learns patterns in the table, not chat prose. I'm upfront about that. πŸ“


πŸ”¨ How I Built It

1️⃣ Real training pipeline

python scripts/fetch_real_data.py
Enter fullscreen mode Exit fullscreen mode

Pulls daily ERA5 weather from Open-Meteo for every city above. Regeneratable. Documented in data/DATA_SOURCES.md.

2️⃣ TabPFN as the classifier

from tabpfn_client import TabPFNClassifier

model = TabPFNClassifier()
model.fit(X_train, y_train)           # real rows
proba = model.predict_proba(X_today)  # wait / walk / garden
Enter fullscreen mode Exit fullscreen mode

Open-weight tabular model. Swap it without rewriting the product. πŸ”

3️⃣ Live weather endpoint

GET /api/weather?lat=&lon= returns today's conditions + frost lag.

  • 🌐 Primary: Open-Meteo forecast with past_days=92 for frost history
  • πŸ›‘οΈ Fallback: nearest city's real ERA5 row for today's calendar day (when API rate-limits on free hosting)

4️⃣ UI that stays out of the way

No chat bubble. No purple gradients. One brand (PLOT), one CTA, one result card. ✨

  • πŸ™οΈ City presets across 12 climates
  • πŸ“ Use my location (browser geolocation)
  • πŸ”„ Refresh live weather
  • βœ… Checklist that ends at the door

5️⃣ Deployed on Render

render.yaml blueprint, health check at /api/healthz, TABPFN_TOKEN in env (never committed). πŸ”’


πŸ’» Code

GitHub logo PranjalManhgaye / plot-touch-grass

PLOT - TabPFN outdoor go-signal for Hacktoberfest Touch Grass

PLOT

Leave the screen. Tend the ground.

PLOT is a Hacktoberfest Week 1 (Touch Grass) project. It uses Prior Labs TabPFN on real weather data (Open-Meteo ERA5) to classify today’s outdoor action as wait, walk, or garden β€” then gives a short checklist meant to end at your door.

Live demo

Pick a city or use your location β†’ live weather loads β†’ TabPFN predicts β†’ go outside.

Real data (not synthetic)






























What Source
Training rows
30,684 daily observations, 12 US cities, 2018–2024
Weather
Open-Meteo ERA5 reanalysis
Frost lag Computed from real daily min temps ≀ 0 Β°C
Labels Transparent horticulture heuristics (backend/labels.py)
Live inputs Open-Meteo forecast + 120-day archive

See data/DATA_SOURCES.md for full provenance.

Quick start

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env   # set TABPFN_TOKEN
PYTHONPATH=. uvicorn backend.main:app --reload --host 127.0.0.1 --port
…
Enter fullscreen mode Exit fullscreen mode
plot/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ engine.py      # TabPFN + transparent baseline
β”‚   β”œβ”€β”€ weather.py     # Open-Meteo live + ERA5 fallback
β”‚   β”œβ”€β”€ labels.py      # Documented outdoor-action heuristics
β”‚   └── main.py        # FastAPI routes
β”œβ”€β”€ data/
β”‚   └── outdoor_history.csv   # 30,684 real ERA5 rows
β”œβ”€β”€ scripts/
β”‚   └── fetch_real_data.py
└── web/               # Static UI
Enter fullscreen mode Exit fullscreen mode

πŸ”“ Why Does Open Innovation Matter?

Frost and planting decisions are tabular πŸ“‹. They belong in a spreadsheet, not a chat thread. πŸ’¬βŒ

πŸ”’ Closed approach 🌱 Open approach (PLOT)
Garden API locks your coordinates to a vendor Open-Meteo: free ERA5, no key
Chat model guesses from prose TabPFN: probabilities over features
Can't explain why without prompt engineering garden: 83%, wait: 9%, walk: 8%
Per-token cost at scale Tabular fit once, predict cheaply
Model swap = rewrite the app Swap TabPFN version, keep the CSV

πŸ” Privacy: we don't store your location. Weather is fetched per request. Training table ships with the repo and is auditable.

πŸ•οΈ Offline path: the CSV + open model path means this could run on a laptop in the backcountry with cached rows. That's the Touch Grass future I want.

A closed chat API wouldn't know what to do with days_since_last_frost: 208. TabPFN was built for exactly that column. 🎯


πŸ† What I'd tell judges

🌿 Theme fit Screen is the shortest part; checklist ends at the door
🧠 Real open AI TabPFN on 30k+ ERA5 rows, not a wrapper
πŸ“ Honest labels Heuristics documented, not pretending it's human survey data
πŸš€ Shipped Live URL, GitHub, Render deploy
🚫 No chatbot cosplay Tabular foundation model where it actually belongs

πŸ€– My Agent Session

Built with TabPFN docs + Open-Meteo API. Happy to answer questions in the comments. πŸ’¬


🎁 Prize Categories

  • 🧠 Best Use of TabPFN - core classifier on real frost/weather tables
  • ☁️ Best Use of Render - production deploy at plot-touch-grass.onrender.com

πŸ”— Links

Resource URL
πŸš€ Live app plot-touch-grass.onrender.com
πŸ’» GitHub PranjalManhgaye/plot-touch-grass
🌦️ Open-Meteo open-meteo.com
🧠 TabPFN docs.priorlabs.ai
☁️ Render render.com

Thanks for reading. Now go touch some grass. πŸŒΏπŸ‘‹

Top comments (7)

Collapse
 
amanmaurya92 profile image
Aman Maurya •

Nice Work!

Collapse
 
aryan_tyagi profile image
Aryan Tyagi •

solid work!

Collapse
 
harsh_vardhanpandey_08fc profile image
Harsh Vardhan Pandey •

Great Build!!

Collapse
 
sashang_c51ba9d1224d19c4a profile image
Sashang •

Nice build.

Collapse
 
aman_kushwaha_af662bcb1db profile image
Aman Kushwaha •

Great work! The project looks impressive. πŸ‘

Collapse
 
dheeraj_yadav_a575d14c6b3 profile image
Dheeraj Yadav •

Impressive !

Collapse
 
yan_sudarshan profile image
Sudarshan Yanpallewar •

Great project πŸ‘