Inspiration
If you've lived through a Gainesville summer, you know the schedule. It's sunny until about 3 PM, then the sky turns dark, the rain comes sideways, and you start counting the seconds between the flash and the thunder. We get to go inside. The people building the power lines that keep our AC running usually don't.
When we read the PlanIT Control challenge, one small detail stuck with us: someone saw a gator next to the job site, and that information lived in one person's text messages. That one sentence is the whole problem. None of the dangers in that story were a surprise. The heat forecast was public. The storm was on radar. The rain gauges were online. It just wasn't in one place, and nobody had turned it into a yes or no before the crew pulled up at 6:45 in the morning.
So we started with a simple question: can a supervisor know tonight whether tomorrow is a safe day to work, and why?
What it does
Picture a supervisor responsible for a dozen job sites. At 6 PM, they get a short briefing for each one, written for tomorrow. It says whether the day is a go, a caution, or a no-go, gives the real reason (maybe the heat index passes 103°F by noon and storms are likely mid-afternoon), and lays out the hours that are actually safe to work. When they open the dashboard, every site is on one map, sorted so the riskiest ones are at the top.
During the day, it keeps watching. If lightning strikes within 10 miles of a site, that site goes to STOP WORK and a 30-minute countdown starts. Another strike resets the clock. When the time runs out, the app doesn't just call it safe; a supervisor still has to sign off before anyone goes back to work.
Crews can add what the data can't see. A crew member can pin a gator, a washed-out road, or standing water to the map from their phone. Their team sees it right away, wildlife sightings get shared with nearby sites, and all of it stays on record for whoever works that site next.
Behind all of it is a 0–10 hazard index for heat, storms, flooding, wildfire and wildlife, learned from seven years of history at 96 real U.S. power plants (the dashboard tracks 153).
How we built it
There were three of us, so we split the work by layer: one person on the backend and alerts, one on the models, and one on the dashboard. In the first hour we agreed on what a site's risk object would look like in JSON, so all three of us could build at the same time.
The backend is FastAPI on PostgreSQL, hosted on Tiger Data. A background worker pulls forecasts, alerts and observations from the National Weather Service, river levels from USGS, and active fire detections from NASA FIRMS. It runs the alert rules and pushes every change to the dashboard over a live stream.
For the models, we gathered seven years of hourly weather plus every record of something actually going wrong near each site: NOAA storm reports, NWS warnings, OSHA heat injury reports, satellite fire detections, river gauges, tide stations, and wildlife sightings. We trained a LightGBM model for each hazard on 2019–2023 and tested on 2025, a year it had never seen. SHAP tells us which factors pushed a score up, so the app can say "heat index 12°F above normal for this time of year" or "river at 140% of flood stage" instead of just "7.2."
The frontend is React and TypeScript with shadcn/ui and Leaflet for the maps.
Challenges we ran into
Our first index cried wolf. It called no-go on almost half of summer days along the Gulf Coast and in Florida. A tool like that gets ignored fast, because a crew sent home every afternoon stops listening. The fix was deciding what actually counts as a thunderstorm day. One rumble of thunder didn't count anymore; three or more hours did. That brought summer no-go days down to about one in six.
There was no lightning in our training data. The free weather archive we used never records thunderstorms at all. We ended up using thunder reports from airport weather stations near each site, which turned out to be the best lightning record we could find.
The AI-written briefings were confidently wrong. In our first tests, the briefings left out an active lightning alert in 6 out of 9 cases, and sometimes made up a reason for a no-go. That scared us more than anything else this weekend. A briefing that sounds sure and is wrong is worse than no briefing. So we built a checker that reads every draft before it goes out (more on that below).
Rate limits. The free weather API capped us at about 8,500 calls a day, so only 96 of the 200 sites we planned have full history so far.
Accomplishments that we're proud of
The moment it clicked for us was the backtest. We ran the model through the July 2025 flash flood in Williamson County, Texas, near the Hal C Weaver power plant in Austin. As the rain piled up, it moved to no-go on July 3, 4 and 5, and hit 9.9 out of 10 on the day of the flood. (That test uses the real weather for each day, so it shows the model reacts to the right signals, not that it can see the future.)
Looking at all of 2025, 70% of the damaging storms that hit within 25 miles of one of our sites got a caution or no-go from us that day. All four hazard models beat the simple "how often does this happen here in this month" baseline, and the heat and storm models did just as well on sites they had never seen.
We're also proud of the things it refuses to do. It won't tell a crew lightning is over, it won't borrow a nearby site's score when it doesn't have one, and it won't show stale data as if it were live.
What we learned
Read the output, not just the metrics. Our briefing writer passed 97% of automatic checks in the first round, and it was still leaving out lightning alerts. We only caught that by reading the drafts one by one.
The data was never the hard part. Almost everything we used is free and public. The work was in stitching it together and deciding what counts as a "bad day."
And for a safety tool, saying "we don't know" is a feature. Old data, missing sites, and the wildlife score (a heuristic, not a trained model) are all labeled as what they are.
What's next for Precognition
- A licensed real-time lightning feed (the stop-work logic is ready for it)
- Text message alerts for crews who aren't looking at a screen
- Photo uploads on hazard reports, and offline support for sites with no signal
- Finishing the weather download so all 200 sites get a score
Built With
- alembic
- docker
- fastapi
- gemini
- hugging-face
- leaflet.js
- lightgbm
- mlx
- nasa-firms
- noaa
- pandas
- postgresql
- python
- react
- scikit-learn
- shadcn-ui
- shap
- sqlalchemy
- tailwindcss
- tanstack
- tiger-data
- timescaledb
- typescript
- usgs
- vite
Log in or sign up for Devpost to join the conversation.