SEASONS APP

A hand-crafted presence journal built on one idea: nothing stays, and a journal should hold that, not rush to fix it.

Role
Sole designer & engineer
Stack
Next.js / Cloudflare Workers / Claude API
Year
July, 2026
Open the live app →
Scroll
This page wears a season,
Like the app does. Try one.

Feelings are seasons, not states.

It began with a conviction I'd learned the hard way: feelings are seasons, not states. In a good season the journal helps you savor what's here; in a hard one it holds you, and reminds you that winter turns. Not two products, one philosophy seen from two sides, and a person moves between them.

Four hand-painted watercolor seasons from the app's intro: bare winter, first buds, full summer, falling leaves
The four seasons, hand-painted and crafted for the app's intro
Notice the small, ordinary things while they're here. Any of them could quietly be a last time.

A season for the chapter, weather for the day.

A season of life moves over months; a mood moves daily. So the app separates them. Your season is chosen once at onboarding and tones every prompt; a light weather check-in tints each day on top. Compose one below: this is the exact line the app would hand you.

Today's weather
Your season
Today's prompt

A flat, in-between day. What's sitting with you?

Nothing you write is saved or sent.
Opener from the weather, core from the season: opener + core is the app's real composition rule

Suggest, don't dictate.

Choosing a season is the first real act in the app, and there are two doors in. The first is for people who already know where they are: four hand-drawn tiles, one decisive tap, done. The second waits on the same screen, a single quiet line at the bottom.

Season choice screen: the heading What season are you in right now, four rows for Winter, Spring, Summer, and Autumn, each with a hand-drawn mark and a short description, and the line Not sure? Take a quick survey at the bottom
Onboarding flow · Both doors, one screen

The second door is for anyone unsure: a quick survey that reads words instead of demanding answers. Pick the handful that feel true, name the direction you're mostly facing, and the word-read proposes a season. That reflection is the only place AI appears in the product: once, at the door, where there are words worth reflecting. Nowhere else. And because a proposal about someone's state can be wrong, the result is built to be stepped past: accept it in one tap, or ignore it and pick for yourself.

Survey entry: the season choice screen, where the quiet line Not sure? Take a quick survey starts the flow
Survey word step: the heading Which of these feel true right now, the instruction to pick five to ten words, a grid of feeling words like Heavy, Tender, Hopeful, and Grateful, and a Continue button
Survey direction step: the heading And right now, you're mostly, with four options: Getting through something hard, Finding your footing again, In a good stretch, In the middle of change
Survey result: a spring watercolor, the heading This sounds like Spring, a short reflection paragraph, a filled Yes that's me button, and a Not quite let me pick line
The survey, step by step: the quiet line in, the words, the direction, the proposal
The app proposes; it never locks.

AI where it helps, never where it decides.

The word-read is a hybrid on purpose. A deterministic score on your device decides the season, so the outcome stays explainable and private. Claude writes only the reflection, the one place language quality matters. The response is validated before it renders, and a register-locked template stands behind it.

Your device's step, animated: the survey's word screen, Which of these feel true right now, with feeling words being picked toward the Continue button The Worker's input, animated: the free-text step Anything you'd add, in your own words, optional, with a Continue button and a Skip line Validate's subject: a summer result, the heading This sounds like Summer with a long, loose reflection paragraph, the shape and register the check reads before render The fallback: the same summer result in the register-locked template's short voice, This is a season to be in, not to rush past
Tap the stops below to walk it: your words in, the reading beat, the reflection back, and the fallback in the same voice
The AI never picks the season.
Degrades invisibly: no key, no network, same product

Built for the entry that isn't journaling.

Some entries during onboarding aren't reflection; they're someone in trouble.

Seasons isn't a therapy product, and it doesn't pretend to be one. But there is exactly one moment where the product reads your words, the word-read at onboarding, and it runs once. If what someone writes in that one moment isn't about seasons, that moment should be guarded.

So Seasons watches it with two nets. The first is a small, auditable pattern list that runs on the device: anything it recognizes never leaves the phone, the AI is skipped entirely, and the answer is fixed, written copy. Anything the patterns let through travels to the reflection service as it normally would, and a second, semantic net reads it there for what a list can't name. That second net adds no new exposure; it only reads what was already on its way. And whichever net hears you, the response never depends on a model: it is always the same fixed, written care.

The response is deliberately small. The entry is acknowledged once, in the app's own quiet voice, and one crisis resource is offered, a single tappable line. The care screen itself wears ordinary clothes. It is structurally identical to a normal result: same shape, same quiet order, nothing in the layout that announces something is wrong with you. Care shouldn't feel like an alarm.

The care response: an autumn watercolor, the heading For now, this sounds like Autumn, the acknowledgment that this sounds heavier than a season with 988 offered, and Call 988 Suicide and Crisis Lifeline as a single tappable line
Agency runs both directions: the destructive path exists, and it is never the easy slip
A recognized crisis never leaves the device.

Two nets, honestly limited. The pattern net catches the phrasings it can name; the AI net reads for what patterns can't, but it only exists when the network does, because the fallback path is deliberately local. Some heavy sentences will pass through unflagged. That cost is accepted on purpose: a net wide enough to catch everything would flag ordinary hard days as crises, and a journal that pathologizes a rough Tuesday has broken its first promise.

Seasons doesn't promise perfect detection. It promises that when it hears you, it answers gently, offers one real number, and keeps nothing.

Nothing sits behind a gate: no lockout, no streak logic, no follow-up nudges.

Even leaving is designed.
Delete your data dialog: the warning that deletion clears entries, name, and season, with a filled Not now button and a plain Delete everything text button
"Delete everything" is the quiet button, "Not now" wears the fill, and a stray tap outside the card can never erase a journal

Every mark in it is hand-crafted.

The typeface is my handwriting. The seasons are watercolors. The stamps that close each entry are drawn one by one. None of it is decoration; it's the register the product speaks in, soft enough that a heavy idea can land lightly. I built this having been through a winter of my own; it's the thing I wish I'd had.

The reading beat holds a minimum of four seconds, even when the answer comes back faster. Care shouldn't look instant.

WinterSpringSummerAutumn SunnyCloudyRainyStormy
The eight season and weather words, set live in a handwritten typeface I drew
Nothing you write here is saved or sent. It's just yours, for a moment.
The four watercolor heroes double as legends: tap one and it dyes this page too

The watercolors are honest stand-ins: generated to one consistent style so V1 could ship on time, and marked for my own brush. The typeface, the icons, and the stamps are already my hand.

Sixteen stamps: saving an entry earns one, the small ritual that closes each day

Governance with teeth.

Shipping solo means being your own QA. Every claim this page makes about the app is backed by a check that fails the build when it stops being true.

0QA assertions
0Scenarios
0Logged decisions
AAIn every mode
  1. Claimed Every screen stays readable, in all four seasons.
  2. Tested So I had a script check every text-and-background pair, across all four palettes.
  3. Caught The checker caught one accessibility miss: a pill sitting on one of the watercolor tints was too faint to read, and it failed in every theme.
  4. Fixed I gave that kind of text its own color, dark enough to hold on paint.
  5. Enforced Then I taught the script to guard it, so if I ever break it again, the build fails and blocks, not the reader.
Open the live app →

What stayed

I started Seasons because I wanted to help people through a hard stretch, and to pass on the one thing I had learned: good or bad, nothing stays. Shifting a feeling into a season changes how it sits. A hard day stops being a verdict and becomes weather, something you are in, not something you are. That makes it easier to carry, because seasons turn.

With that mission, I came into this as a product designer who wanted to know if I could build the digital product I designed. The honest answer: not alone, and that turned out to be the lesson. AI wrote most of the code. I made every decision, and I can walk through each of them; the log holds more than thirty, including the ones I reversed. The work of a design engineer, it turns out, is not typing. It is framing and architecting: knowing what should exist, noticing when it is wrong, and refusing to ship until it is right.

The smaller, harder lesson: one conviction is enough, if you never break it. Nothing stays. That sentence chose the prompts, the palette, the button weights, the crisis copy, even the physics of the stickers on this page. Every time a decision got difficult, the tiebreak was already written.

Seasons is a season too. V2 is the motion pass, built with my own hands this time, and a native iOS release. Nothing stays, and that includes the parts of this I have not learned yet.

Next Project
Jackpot · The 0 → 1 Foundation