Experimental or in-progress: In development

SeaChange: abstract signals, explained

A personal iOS project in explainability. It reads a shifting set of live coastal signals and turns them into a plain-language read on what your local beach is doing and whether it is worth heading down.

Personal project

2026

View more work
  • iOS / SwiftUI
  • Particle systems
  • API & data
  • Product design
  • Design engineering
The sea at dusk

The problem

Temperature, wind, swell, tide, UV. Half a dozen readings, all moving at once and each trending its own way through the day. Most people cannot turn that into the one answer they want: is the beach worth it, and why.

SeaChange does the reading for you.

A day at your favourite beach

Most forecasting apps hand you a week of data and assume you will do the reading. SeaChange takes the opposite bet. The whole app is one screen: a single 24 hour timeline for one beach, one stop per hour from now until this time tomorrow. Not a seven day forecast, just the day ahead.

The readings drift all day, no two in step: wind easing off, tide climbing, swell dropping, UV falling with the sun. On their own they ask you to be a meteorologist. SeaChange turns that into one plain read.

Open-MeteoForecastBOMLive obsSwellMarineTidesHigh, LowSunDay, Night
Live data sources funnelled into one screen you can read at a glance.

Inside the app, those sources become a handful of live signals.

Wind speedEasing9 kn
Wind dirOffshore110°
Air tempCooling34°C
SwellDropping1.2 m
TideRising1.4 m
UV indexFallingUV 2

Six live signals are the input. Below is what SeaChange outpu.

The same conditions as raw readings, and the plain-language summary SeaChange composes from them.
The readings, 5:40pmWhat SeaChange says

The readings, 5:40pm

Air temp     34 C
Wind speed   9 kn   (Beaufort 3)
Wind dir     110 deg  -> offshore
Sky / rain   clear, dry
Trend        easing across the arvo

How the sentence is constructed

[temperature][ + rain], [wind clause]. [one optional trailer]

It fills a fixed skeleton from a set lexicon and grammar rules held in code, with just enough seeded variation, keyed per beach and day, that a day always reads consistently to itself.

What SeaChange says

Bloody hot, with a fresh offshore breeze. An arvo glass off might be on.

Three small engines do the work.

The first classifies wind on the Beaufort scale and decides the glass off state. Detection stays separate from anything visual, and “approaching” is only ever earned from a falling trend, never a single calm reading.

The second measures wind direction against each beach’s own orientation, so the same westerly is offshore at one beach and onshore at another.

The third writes the sentence, and no language model touches it.

The same Beaufort thresholds run in TypeScript on the server, so the sentence on screen and the push you receive can never disagree.

Summaries for some and detail for others

Scroll past the summary and the full Detailed Readings panel provides granular wind speed, direction and gusts; temperature, range, humidity and UV; swell and the next tide; cloud and rain; sunrise and sunset. Every reading carries a trend arrow and moves hour by hour as you scrub the timeline. The human readable summary helps when reviewing at a glance, the detailed readings are for the people who really want to interrogate the patterns.

The SeaChange Readings panel: wind, air, sea, sky and sun, each metric with its value and hourly trend
The full Detailed Readings panel, one scroll below the summary. Wind, air, sea, sky and sun, every value with its hourly trend.

Co-developed, not vibe coded

I’m building SeaChange in Swift, with Claude Code as a collaborator, not an autopilot.

One file, Agent.md, is the source of truth: spec, operating rules, and a dated decision log in one place. Every feature earns a priority tier before a line is written, functionality comes before form, and WCAG AA contrast is a hard gate. 14 test suites cover the parts that are dangerous to get wrong, like the wind classification and the language engine. And the agent cannot trigger device builds on its own, because those cost real money.

priority log · functionality before form

[x]  P0      APNs push alerts, verified on device
[x]  P1 #5   The 24-hour "day at the beach" timeline
[x]  P1 #6   Plain-language summary (fixed lexicon)
[x]  P1 #13  Per-beach wind, offshore vs onshore
[x]  P2 #7   Location picker, 66 beaches
[~]  P2 #10  Sea breeze alerts, backend pending
[ ]  P2 #1   Wind speed units, km/h toggle
[ ]  P3 #2   Sign in with Google
[ ]  P3      First-run onboarding stepper
[ ]  P4 #22  Day and night shift on scrub
[ ]  P4      Particle sea beauty pass (parked)

One model from four messy sources

Real coastal data is partial and inconsistent. A wind direction comes back as an integer, a decimal, or nothing at all when it is dead calm. Live observations cover the last half hour and carry no forecast. The data layer exists to make that mess invisible.

Four sources fold into one internal model:

  • Open-Meteo: forecast and marine swell, temperature, wind, gusts, UV, weather codes.
  • Bureau of Meteorology: live Australian station obs, an hourly forecast, the next high and low tide.
  • Supabase: accounts, saved beaches, the alert state machine, and the scheduled server side check.
  • Apple Push Notification service: the alerts, including the spoken ones.

The fetches run in parallel, everything converted to knots on the way in.

Teaching the words

Explaining a forecast only helps if the words mean something to you. A lot of coastal language is quietly technical: offshore, onshore, swell, Beaufort, glass off. SeaChange never assumes you know it. Every term links to a plain definition in the app, so the summary teaches the words as you go. Read a few and you start to read the beach yourself.

The SeaChange in-app glossary, coastal terms each with a plain-language definition
The in-app glossary. Every term the summary uses is one tap from a plain definition.

A living sea in Metal

The horizon on the home screen is not a looping video or a gradient. It is a real 3D wave field: thousands of points on a height map, projected through an actual perspective camera and drawn on the GPU with Metal. It runs at 60 frames per second, eases between states independently of frame rate, and pauses itself in the background.

Two things about the forecast drive how it looks, and they are kept independent on purpose.

Wind speed and shore-relative direction drive the water. Time of day drives the sky behind it.

A light breeze rolls slow and rounded. As it picks up, the sea churns faster and the chop sharpens. Wind direction sets the roughness. Offshore stays glassy, onshore turns jagged. A light onshore breeze will look rougher than a strong offshore one, the same way as happens in the ocean.

Manly, with a light offshore breeze. The wind comes off the land and the sea stays glassy.
Cottesloe, with an onshore breeze straight off the sea, and the surface breaks into chop.

Time of day is the third input, but it drives the sky behind the water rather than the particles themselves.

Temperature and the weather code feed the readings and the sentence, not the animation.

Closing the loop

Everything so far happens on screen, but you should not have to keep checking it. A job on the server runs on a schedule, applies the same wind logic as the app, and when a beach you care about tips into glass off, it sends a push. The ocean goes calm, and your phone tells you, whether or not the app is open.

A SeaChange push notification on the iPhone home screen: Cottesloe Beach has a glass off, the wind has dropped and the sea just went glassy
A push the moment your beach goes glass off, no need to open the app.

Where it’s at

SeaChange is shipping shaped, not shipped. The detection, the data pipeline, the timeline and the Metal sea are all built and tested. The next big piece is a server side sea breeze alert, which is designed and half built. Beyond that it aims wider than tracking glass offs and will help people plan which windows are worth their time, which are not, and why.

9:41
Best windows
Cottesloe Beach · next 4 days Planned
The days ahead
Fri5 Sep
Best 6–9amglassy, light offshore
Sat6 Sep
Best 6–10amcalm at dawn
Sun7 Sep
Best 6–11amglassy, light offshore
Mon8 Sep
Best 7–9ambreeze builds later
6a7a8a9a10a11a12p1p2p3p4p5p6p7p
HomeLocationsGlossarySettings
Potential future release: A concept for a multi-day planner to help people identify a beach's best windows over coming days.

Watch this space...

SeaChange hopes to close the distance between a overwhelming amount of coastal data and a person just trying to decide whether the beach is worth it, and why. It's also an experiment. Can I apply my skills in software building methodology to a language I'm not familiar with using AI as my co-pilot? So far so good.