OlaEcuador — A surf forecast that checks its own homework
September 30, 2026
Overview
OlaEcuador answers one question: at what time is it actually worth getting in the sea? It scores every hour of the coming week for a stretch of Ecuador's Pacific coast, both for surfing and for a plain day at the beach, by combining free wave and wind models with Ecuador's official INOCAR tides, local daylight, and INOCAR's own sea-state alerts.I designed and built it — the data pipeline, the scoring, the map, the charts, and the interface.What makes it more than another forecast skin is the part most forecasts skip: it is built to find out whether its own numbers are true. This is a validation project, and honesty about uncertainty is the whole point.
The real problem
Ecuador's coast is not well served by the big surf forecasts. The global models exist, but they are sampled offshore, in deep water, and the number a surfer cares about — the wave that actually breaks at Montañita at 7am — is the product of a dozen local factors those models smooth over.So the honest starting question was not "how do I display a forecast?" It was: does free model data, sampled about 5 km offshore, say anything useful about the waves surfers actually get here? The first release is deliberately scoped as a validation spike on two spots, Montañita and Engabao, to answer exactly that before pretending to cover the whole coast.Designing around that question, rather than around a pretty forecast card, is what shaped everything else.
How the score works
Each hour gets a surf score built from factors that multiply together, so any one bad factor drags the whole hour down — which is how surf actually works:
Size is not the raw model height. Each swell train is scaled by exposure — full marks inside the spot's swell window, fading to zero as the angle moves 30° outside it, and reduced further when the swell arrives obliquely. The exposed swell is turned into a breaking height (using the Komar and Gaudiano 1983 relation), combined across trains by energy, and compared to the spot's ideal wave.
Wind is weighted by how onshore it is relative to the direction the beach faces. Onshore wind counts almost fully against the score; offshore barely touches it.
Tide compares the INOCAR stage to the surrounding hours and matches it to the spot's preferred tide. It softens a score but never zeroes it.
A separate beach-day score is a weighted geometric mean of calm water, light wind, no rain, sun and warmth, times daylight — because "nice day at the beach" and "good surf" are different questions.
INOCAR alerts override everything: a rough-sea alert caps the score, a very-rough alert all but zeroes it, and those hours are never suggested as "best".
Every score carries its component breakdown and human-readable reasons, so the interface can always explain why an hour scored what it did rather than just showing a number.
The interface
The coast dashboard is a MapLibre map of the live sea-state field — a grid of ocean cells coloured by wave height with arrows for direction of travel, switchable to the wind field — with each spot coloured by its score. You can press play and scrub through the week and watch the swell arrive. Around the map sit KPI tiles with sparklines, a spot ranking, a swell rose set against each spot's working window, and a meteogram.The spot lab is where the real work shows. A nine-day heatmap of hourly scores opens into an hour detail with its reasons and a beach compass. It draws the INOCAR tide curve against Open-Meteo's own modelled tide so you can see them disagree. And it exposes the model spread: three wave models against six wind models, eighteen combinations, because near the coast they disagree enough that hiding it would be dishonest.
The part that makes it real: the field log
Any forecast can look authoritative. This one is built to be checked.Before or after a session, you open the spot, tap the hour, and log what actually happened in the field log: a one-to-five rating, the size in feet, the wind you felt, and where the information came from — your own session, or what local surfers and schools reported. Each entry freezes what all eighteen model combinations predicted for that hour at the moment of logging.Then an agreement table ranks the combinations by mean error and bias. With twenty or more entries per spot, it tells you which wave and wind model to trust near this coast, and whether the score is systematically optimistic. If a spot is consistently wrong in one direction, a tuning panel adjusts its facing, swell window, best tide or ideal size, and the page re-scores live.That loop — predict, record reality, measure the gap, tune — is the product. Everything else is in service of it.
What the data actually showed
Building the validation tooling immediately produced findings worth having, which is the point of building it:
INOCAR's 2026 tides exist as open data — an hourly CSV in local time — but cover nine stations, not the twenty-five you might assume. La Libertad is the nearest to both spots. Open-Meteo's own modelled tide matches the phase to within about an hour but overshoots the range, so the official INOCAR data wins.
The marine model grid is coarse — about nine kilometres — and land cells return nothing, so the app deliberately snaps each spot to a sensible ocean cell rather than the merely nearest one.
The models disagree a lot near the coast. On an early run, Montañita's predicted daily peak ranged from 37 to 77 depending on the model combination. One model called the primary swell a short-period wind sea while another reported a long-period groundswell for the very same hour. Midday wind ranged from 6 to 20 km/h across models. That disagreement is precisely what the field log is there to settle — and precisely why a single-number forecast for this coast would be a confident lie.
Technologies used
Framework: Next.js 16 (App Router, static pages refreshed on a 3-hour interval) and React 19.
Map: MapLibre GL with OpenFreeMap tiles — no API key, commercial use allowed.
Charts: ECharts, tree-shaken, for the meteogram, timeline and swell rose.
Data: Open-Meteo marine and weather models (all combinations fetched in one batched call), INOCAR tide CSVs, INOCAR sea-state alerts.
Styling: plain CSS custom properties with light and dark themes.
Testing: Vitest across the scoring and the tide parser.
Tooling: a command-line "spike" that prints the hourly table for any spot and model combination and dumps every hour to CSV, so the model comparison can be run without the browser.
The scoring is pure TypeScript with no input or output of its own, shared unchanged between the server, the command line and the browser — which means the eventual scheduled job that writes scores to a database can reuse exactly the same code the interface runs.
Challenges and learnings
Scoping to a question, not a coastline. The disciplined move was to ship two spots and a validation loop rather than a whole-coast forecast that looks finished and might be wrong. A forecast you cannot check is decoration.Model disagreement is a design problem, not a bug to hide. The instinct is to pick one model and present a clean number. Near this coast that would be dishonest, so the spread is surfaced deliberately and the field log exists to eventually collapse it into a justified choice.Free data comes with real limits, and naming them is the work. Open-Meteo's free tier is non-commercial, the marine grid is coarse, and the modelled tide overshoots. Each of those is written down in the project rather than papered over, because a forecast's credibility is exactly its honesty about what it does not know.
Outcome
A working, honest surf and beach-day forecast for two Ecuadorian spots, wrapped in the tooling to prove whether it deserves to be trusted — the map to see the week, the lab to understand an hour, and the field log to grade the forecast against the sea itself. It is built to expand to the rest of the coast only once the data has earned it, and every piece of the scoring is already shaped to move to a scheduled backend without a rewrite.The site is careful to say what it is: it shows when conditions look pleasant, not when they are safe. Respect the flags, the lifeguards, and INOCAR's alerts.