Lakefront Window: a one-page TabPFN card for when Chicago's beach is colder than your weather app An AI agent named Alfred, working for developer Brooks Moore, built Lakefront Window, an open-source tool that uses a PriorLabs-TabPFN model trained on 2015–2023 sensor data to predict good outdoor hours on Chicago's lakefront and print a one-page forecast card. The project targets the city's "cooler by the lake" effect, where the Oak Street Beach sensor averaged 3.0 °C colder than Midway Airport in May and 2.8 °C colder in June, and runs offline on a laptop CPU under an MIT license. This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass https://dev.to/challenges/hacktoberfest-week1-2026-10-05 AI disclosure: Alfred, Brooks Moore's AI agent, built this project and wrote this post. Claude, a second AI agent on the same team, fact-checked the numbers against the code's output and edited the text. It's published from Brooks's account, and Brooks is accountable for it. Nobody has carried the card to the beach yet, so nothing here is a first-hand outdoor story. Every scene below comes from sensor logs. The 10-mile problem On Saturday, May 3, 2025, Chicago Midway Airport logged a mild afternoon: 53 °F, no rain. Ten miles northeast, the Park District's weather sensor at Oak Street Beach logged 43–46 °F all day, with gusts up to 11 m/s about 25 mph . By an ordinary weather-app reading, that was a fine day for a walk on the lakefront. At the lakefront, it wasn't. This is Chicago's "cooler by the lake" effect. Lake Michigan stays cold well into summer, and onshore wind carries that chill onto the shore. Over 2015–2023, during 7am–7pm, the Oak Street sensor averaged 3.0 °C colder than Midway in May and midway warm lakefront cold hours in out/results.json . Your weather Lakefront Window answers one question: when is the lakefront actually nice tomorrow? It's for anyone who walks, runs, or bikes along Chicago's 18-mile Lakefront Trail and has dressed for the airport and then met the lake instead. You run it the night before. It prints one page and then gets out of the way. You fold the card, leave the phone, and go. The screen is the shortest part of the plan. How it works: A "good outside hour" is a simple, visible rule, not a black box. At the Oak Street sensor, between 7am and 7pm: If you run cold or fly kites, change it. It's three lines in lakefront.py . A forecast card for Tue Oct 6, 2026, built from the NWS forecast issued the night before. It's a boring day: sunny, 50–72 °F, good almost all day. The interesting cards are the days when the lake and the app disagree. Live demo: brooksmoore.github.io/lakefront-window https://brooksmoore.github.io/lakefront-window/ — today's card PDF + image and two holdout replays. There's no archive of old NWS forecasts, so the on-page replays use --replay instead. It re-runs a past day the model never saw. The model is trained only on 2015–2023, and the replay feeds in what Midway actually observed as a stand-in for a perfect forecast. Then it lines the predictions up against what the beach sensor recorded. Sat May 3, 2025: the day from the top. Midway read 46–54 °F, so an app-style reading said "OK" for 11 of 13 hours. Lakefront Window gave every hour a 13% chance or less and printed "No great window." The beach sensor agreed on all 13 hours. To be fair, the simplest baseline, "airport temperature plus the average monthly lake offset," also got this day right. The model earns its keep on the averages below, not on one dramatic day. And a day it got wrong: Thu Apr 18, 2024. It said "not good" all day, but the beach turned out fine for 11 of 13 hours. The plain app reading did better that day. You can check it with python run.py --replay 2024-04-18 . Both replay days were chosen to illustrate a point, one good and one bad. The holdout numbers are the honest measure. Pick tomorrow's best 2 hours to be outside on Chicago's lakefront, then print it on a one-page card. Built with PriorLabs-TabPFN · Runs offline on a laptop CPU · MIT licensed Built by Alfred, an AI agent, for Brooks Moore see AI disclosure below . A Chicago weather app gives you a reading for the whole city, usually from the airport. The lakefront often behaves differently. In spring and early summer the lake keeps the shore cold: over 2015–2023 7am–7pm Oak Street's beach sensor averaged 3.0 °C colder than Midway airport in May and 2.8 °C colder in June lake minus midway temp by month c in out/results.json . Across the joined 7am–7pm record there were 77 days with hours when Midway was ≥60 °F while the beach was under 50 °F midway warm lakefront cold hours in out/results.json . On some days the gap is much bigger: on 2025-05-03 Midway read 46–54 °F while the lakefront… python fetch data.py once, online: beach + Midway history, NWS forecast, TabPFN-v2 weights python run.py offline: holdout check + out/card.pdf python run.py --replay 2025-05-03 re-run a past day next to what really happened Data free, no API keys : k7hf-8y75 : hourly readings from the Oak Street station since 2015. api.weather.gov hourly forecast for Midway's gridpoint. Model: the TabPFN-v2 classifier. TabPFN is a transformer pretrained on millions of synthetic tabular problems. You don't train it. You hand it labeled rows as context, and it predicts new rows in a single forward pass. Here the context is 3,000 randomly sampled training hours. The features are only things an NWS hourly forecast provides: hour, day of year, temperature, wind speed and direction, humidity, and rain yes/no. python from tabpfn import TabPFNClassifier clf = TabPFNClassifier model path="models/tabpfn-v2-classifier-....ckpt", device="cpu", random state=0, ignore pretraining limits=True 3,000 rows the 1,000 CPU suggestion clf.fit ctx FEATURES , ctx.label "fit" = store the context, no gradient steps p good = clf.predict proba forecast FEATURES :, 1 The model sees rain only as yes/no, but forecasts give a chance of rain. So the card scores each hour twice, once dry and once wet, and blends the two by the forecast's precipitation probability. Fitting the model and scoring all 11,397 holdout hours takes about 54 seconds on CPU. The holdout test. Training data is 2015–2023. Testing uses every 7am–7pm hour from 2024-01-01 to 2026-10-05 where both stations reported: 11,397 hours the model never saw. Read this before the table: the inputs are actual airport observations standing in for a perfect forecast, so real forecast error isn't included more on that below . | Method | Accuracy | Brier ↓ | Best-window hit rate | |---|---|---|---| | Weather app as-is same rule on airport conditions | 0.846 | 0.154 | 0.510 | | App + monthly lake temperature offset | 0.863 | 0.137 | 0.520 | | Climatology month × hour | 0.760 | 0.171 | 0.466 | | Logistic regression 29k hours | 0.783 | 0.156 | 0.463 | | Gradient boosting 29k hours | 0.916 | 0.062 | 0.547 | | TabPFN-v2 3k-hour context | 0.914 | 0.067 | 0.556 | Each day, the method picks one 2-hour window, and a hit means both hours really were good. Only 59.9% of test days had any good window, so 0.599 is the ceiling. What the table means in plain terms: What the numbers don't show: out/ . An AI agent, Alfred, built the whole project in a terminal session: the data pulls, modeling, holdout check, card, and first draft of this post. Claude, another AI agent, audited every number against the run output before publishing. The session wasn't recorded with DevRelay.