DeerCast
Prep. Predict. Pursue

A native hunting app — not a website with a thin wrapper. Hunters open iOS or Android in the dark, see today’s free whitetail forecast for their pin, then decide whether 06:40 or 16:10 is the hour worth sitting.

Was ausgeliefert wurde: native iOS (App Store) and native Android (Play Store). Same Node.js API. PostgreSQL for accounts, pins, maps, and receipts. MongoDB for the hour-by-hour forecast documents and weather ingest. No Super Admin web console on this product — the phone is the product.

iOS Android PostgreSQL · MongoDB
Whitetail buck in a Midwest food plot at dawn, timber and a ladder stand on the edge
07:10 Prime
NW 8 mph
Offline cache
Cedar Ridge, Iowa · CR-WEST pin
Timber · food plot · stand — the area the forecast is scored for
iOS · Android
iOS Native · App Store
Android Native · Play Store
PostgreSQL Users, pins, maps, IAP
MongoDB Hourly forecast documents

Mobile only. iOS and Android.

Both stores get the same Node.js API. There is no staff web app on this engagement. If it does not work with gloves, one bar of LTE, and a 5 a.m. battery, it does not ship.

iOS · App Store

Native Swift app: today’s free forecast, saved hunt pins, maps, wind check, and track. Background location only when the hunter opts in for a sit. Store listing: DeerCast — Prep. Predict. Pursue.

App Store

Android · Play Store

Native Kotlin app with the same forecast, map objects, and track flow. Offline map edits write locally, then sync when the ridge has signal again — same contract as iOS.

Play Store

A weather app is not a hunt plan.

Before this build, a hunter with two vacation days stacked a national weather icon, a moon calendar screenshot, and a mapping app that did not know the rut window. “Cold and cloudy” is not an hour. Sitting 05:30–11:00 because the icon looked good burned the only weekday they had.

  • No hour resolutionGeneric forecasts said “good morning.” They did not say 07:10–08:40 on this ridge after a 0.4" overnight rain.
  • Maps lived in another appWaypoints, wind, and property lines were not sitting next to the movement score. Switching apps in a stand is how phones get dropped.
  • No recovery pathA hit at last light meant a forum thread, not a structured track on the same phone that called the sit.
Whitetail at a field edge at last light

Cole H. · Cedar Ridge, Iowa · pin CR-WEST

  1. 21:12 Mon — Opens the iPhone in the kitchen. Free today + tomorrow for CR-WEST. Tuesday 07:00–08:30 tagged Prime after overnight rain and a falling barometer. He sets a sit alarm. Nothing to print.
  2. 05:48 Tue — Walks in on Android (work phone). Forecast still in the on-device cache — ridge has no LTE. Wind check: NW 8. He keeps the west-side pin; east-side food plot would be a swirl.
  3. 07:22 — Movement window he sat for. Two does, then a mature buck on the field edge. The hour matched what MongoDB scored the night before, not a generic “cloudy and cool.”
  4. 16:40 — Optional evening sit is Slow. He does not burn the second vacation day. Track is unused. That is still a win.

Hour-by-hour movement — for that pin

The engine scores each hour from local temperature, wind, barometric trend, cloud cover, precip, lunar feeding windows, and season (pre-rut / rut / late). Today’s forecast is free. Longer horizons sit behind IAP, same as the stores.

Today · Cedar Ridge

Whitetail forecast

CR-WEST · free day · cached

05:00
Slow
06:00
Build
07:00
Prime
08:00
Prime
09:00
Good
10:00
Slow

NW 8 mph · 34°F · baro falling · moon 28%

Hunter checking a phone from a tree stand at first light
On stand Forecast already on the device

What the hunter actually does in the app

01 · Predict

Hour-by-hour forecast

Vorher

A 12-hour weather blob. Sit all morning “just in case.”

Nachher

Each hour has a score for that pin. Cole sits 07:00–08:30 and leaves.

02 · Weather

Weather at the hunt pin

Vorher

Phone weather showed Des Moines or the county seat — not the farm 40 minutes out.

Nachher

Temp, wind, barometer, rain, and moon are scored for the saved pin (CR-WEST), not the nearest town.

03 · Map

Waypoints, parcels, wind, plots

Vorher

Hunt plan in one app, map in another, wind in a third.

Nachher

Pins, food plots, wind check, radar, and crop history sit in the same native map.

04 · Track

Hit location → recovery

Vorher

Guess the blood trail from a group text.

Nachher

Mark the hit on an anatomical model; wait/search guidance is on the same phone.

05 · Offline

Ridge with no bars

Vorher

Spinner. Then a screenshot from last night.

Nachher

Last forecast + map objects cache on device. Sync when LTE returns.

06 · Push

Window alerts

Vorher

They remembered to check at lunch. Window was 07:00.

Nachher

Optional push when tomorrow’s Prime hour lands on a saved pin.

Hunter planning a sit with a phone and a paper map at dawn

Scout on the tailgate. Recover after the shot.

Native map layers: property info, hunting land, custom waypoints, wind check, food plots, live Doppler, virtual rain gauges, aerial, and crop history. Offline edits queue locally so a hunter can drop a pin with no service.

Track is a separate flow: tap the hit on the model, log time and weather already on the pin, then follow wait-vs-search guidance. Session documents land in MongoDB; the hunter identity stays in PostgreSQL.

PostgreSQL for the hunter. MongoDB for the hours.

Two stores on purpose. Relational data that must not drift (who paid, which pin, which parcel) lives in Postgres. High-write, nested, time-bucketed weather and scores live in MongoDB so an hour document can be replaced without a 24-column update.

PostgreSQL

Source of truth for identity and hunt assets. Node.js talks to it over a connection pool. iOS/Android never open the database — only the API.

  • users / devicesApple and Google account links, push tokens, last app version.
  • subscriptions / receiptsApp Store and Play IAP, Elite / Pro / Unlimited entitlements, trial windows.
  • hunt_locationsNamed pins (CR-WEST), lat/lng, timezone — the key the forecast job joins on.
  • waypoints, food_plots, parcel_savesStructured map objects with hunter_id foreign keys.

MongoDB

Document store for anything that arrives as a nested hour array or a radar blob. Indexed on locationId + date.

  • forecast_daysOne document per pin per civil day: 24 hour scores, wind, temp, baro, moon, rut phase.
  • weather_ingestRaw vendor/NWS observations the scorer consumed — kept for audit when a hunter says “this hour was wrong.”
  • radar_frames / rain_gaugesShort-lived tiles the map overlay reads.
  • track_sessions / community_postsHit diagrams, photos, feed items — schema varies; Postgres only stores the owner id.
MongoDB · forecast_days · CR-WEST · 2026-11-18 Scored
{
  "locationId": "loc_cr_west",   // FK in PostgreSQL hunt_locations
  "date": "2026-11-18",
  "hours": [
    { "h": 7, "score": 92, "label": "Prime", "wind": "NW 8", "tempF": 34, "baro": "falling" },
    { "h": 8, "score": 86, "label": "Prime", "wind": "NW 8", "tempF": 35, "baro": "falling" }
  ],
  "moonPct": 28,
  "season": "rut",
  "precipInOvernight": 0.41,
  "engine": "v3.4"
}
MongoDB document locationId is a PostgreSQL hunt_locations row

From weather ingest to a Prime hour on the phone

01

Ingest

Node.js workers pull local weather and moon for every active pin in PostgreSQL. Raw frames land in MongoDB.

02

Score

The movement engine writes a 24-hour document. Prime / Good / Slow is stored per hour, not as a daily slogan.

03

Sync

iOS and Android GET the day for their pins. Today is free. Entitlement for 14-day range is checked in Postgres.

04

Sit

On the ridge the phone reads the cache. Optional push already fired if tomorrow’s Prime hour matched a saved pin.

Native phones. Postgres + MongoDB behind Node.js.

This case study is mobile-only. Native iOS and Android talk REST (and a light sync channel) to a Node.js API. PostgreSQL holds hunters, devices, IAP receipts, pins, and map geometry. MongoDB holds forecast documents, weather ingest, radar, track sessions, and the community feed.

Stores are not interchangeable. You do not put 24 nested hour objects in a Postgres row for every pin every night, and you do not put IAP entitlements in a Mongo document that a hunter can fork.

iOS native Android native Node.js API PostgreSQL MongoDB Offline cache
iOS & Android

Native forecast, maps, track, push, offline queue. Same API contract on both stores.

Node.js API

Auth, entitlements, forecast read, map CRUD, weather jobs, push fan-out.

PostgreSQL

Users, devices, App Store / Play receipts, hunt pins, waypoints, food plots, parcels.

MongoDB

Hour-by-hour forecast documents, weather ingest, radar, track sessions, feed posts.

Was sich nach dem Go-Live geändert hat

Hours, not slogans

Hunters plan around Prime hours on a named pin. Vacation days stop being “sit from dark to 11 because AccuWeather said cloudy.”

One app in the stand

Forecast, wind, parcels, and track share a native shell. No three-app shuffle with gloves on.

Data that can be audited

If a Tuesday score looks wrong, weather_ingest in MongoDB and the pin in PostgreSQL still exist. The model can be retrained; the receipt cannot be guessed.

Need a forecast-class mobile app?

We ship native iOS and Android against a Node.js API, with PostgreSQL for accounts and MongoDB for time-series documents — the same split used on DeerCast.