
Soothe
A native iOS proof of concept that pats you until your stop is near, then wakes you kindly. A 2026 rebuild of my 2020 case study. Every ride is simulated.
- Year
- 2026
- Track
- built
- Category
- case-study
Tools
- Swift
- SwiftUI
- SwiftData
- Core Haptics
- AVAudioEngine
- Claude Code
Soothe lets a commuter rest on the way home. A gentle pat, felt, heard and seen off one clock, says everything is fine until the stop is near. Then a clear, kind “Time to fly.” wakes them. It is a native iOS proof of concept: every screen is playable, and every ride, stop and signal is simulated. No location, no network, no real timetables. I made it as a product design case study in February 2020 and rebuilt it as an app in September 2026, with Claude Code doing the building one step per session.
The ride










Where it started
The 2020 brief asked: have you ever napped on the bus and woken up at the last stop? How do you wake a passenger just before their stop? I answered with saved routes, a tracking screen, statistics, reassuring notifications along the way and a vigorous alarm at the end. The persona was Sıla, an academic in İstanbul who worked overnight three times a week and slept on the second vehicle home, anxious every time.
In 2026 she became Noor, a night-shift nurse in Amsterdam-Noord who rides home exhausted and never lets herself sleep, afraid of the end of the line. A persona, not a research participant. Around her, the 2020 answer was taken apart:
- Routes, Track, Statistics and Settings became Today, Journey, Rest and You.
- Reassurance notifications became the Pat: haptic, sound and light on one clock.
- A pulsate rhythm and white noise became three rhythms, Heartbeat, Pat and Tide, and three ambiences, Rain on the canal, IJ wind and Brown noise.
- The vigorous wake alert became Nearing, firmer a few stops out, and then Arriving: “Time to fly.”, until “I'm awake”.
- Badges became Moments, gentle milestones that are never gamified.
Brainstorming, phase 1
Feelings13
- Boring
- Lethargic
- Nausea
- Tiresome
- Depressive
- Claustrophobic
- Comfortable
- Negative
- Mechanical
- Anxiety
- Mundane
- Familiar
- Unfamiliar
About Solution12
- Childhood
- Multi-Platform Smartwatch
- Desmond Morris
- Process Progress
- Maternal Patting Reassurance
- Chirping
- Haptic Feedback
- Womb
- Headphones
- Cradle
- Multi-vehicular Situations
- Multi-sensory reassurance at every stoptyped
About Travel18
- A Pack of People
- Dark and Dim
- Dusk
- (Sleeping on bus) Effective
- (Corporate Service) Grouping
- Cars
- Complicated
- Range
- (Corporate Service) Hit or Miss
- Read the Plate
- Alot Start
- Crowded
- Possible
- System
- Anxiety
- Busy Mind
- Concrete
- Awareness
Brainstorming, phase 1: feelings, the solution and the travel. 
The sketch notes. The pat, and time to fly, are both here. Main user flow
- User context
- User gets out at the usual hour, walks to the stop she has been gotten on the bus.
- Tech context
- User's device has adequate battery power. Cell coverage is abundant for the first phase.
Phase 1, bus
App starts to listen geolocation due to the time pattern of the user.
- Clock data initiates
App taps into the location sensors and confirms the location is start point of the commute.
- Location data confirmed
According to the automation rules defined by the user (user opted for sound, haptic & white noise) starts as soon as user connects headphones.
- Listening location data
Throughout the first phase of the commute, user hears slow, rhythmic sound and feels haptic feedback simultaneously & synchronized.
- Listening location data
User gets close to the stop to get off the bus and take a train. Now app grasp the situation through location services and changes auditory and haptic feedback to a vigorous rhythm to notify user: time to get off!
- Location data confirmed
- Clock data registers
Phase 2, train
User gets into the subway station. Cell coverage lost. App transitions to accelerometer mode.
- Location data N/A
- Cellular signal lost
By listening accelerometer data, app grasps train's initiation of movement.
- Listening accelerometer data
App counts the stops of the subway utilizing accelerometer data. Throughout the commute, app reinitiates soothing feedback until it is time to get off.
- Listening accelerometer data
User gets close to the stop she needs to exit, this time using accelerometer data and confirm from clock; changes auditory and haptic feedback to a vigorous rhythm to notify user: time to get off again!
- Accelerometer data initiates
- Clock data confirmed
As soon as there is location data to confirm the commute is over, app disengages and registers commute to be found in statistics.
- Location data confirmed
The main flow: location on the bus, the accelerometer on the train. 
Wireframes, sketched in Concepts and tested in Marvel Pop. 
The Track Mode sketch, on a phone. 
The XD screens: one colour for actions, Gill Sans throughout.
What commuters told me
A short questionnaire in 2020 asked about the commute to work and back. For three words on it, most people wrote negative ones: boring, tiring, prolonged. Sleeping through it makes sense. Four findings shaped the app, each with its 2026 answer under it. The board printed no sample size, so I give none.
From my February 2020 questionnaire. Shares of answers as the board printed them. It gives no sample size.
Sleeps on the way, share of answers Answer Share Yes, often 24% Sometimes 19% Rarely 10% No 47% More than half of the people I asked sleep on public transport.
2026Soothe is made for that rest. Its first words are “Rest. We'll keep watch.”
Missed a stop asleep, share of answers Answer Share For a few times 18% Rarely 2% No 80% One in five had missed a stop because they were asleep.
2026So the wake ignores the rider's soft settings, and only “I'm awake” ends it.
How they commute, share of answers Answer Share Company service 35% Bus or metrobus 27% Subway or tram 22% Minibus 5% Cab 4% Ferry 1% Other 5% After company shuttles and buses came the subway and tram, where some riders have no signal.
2026So underground, the design counts stops by motion. In this build that is simulated, with no sensors.
Headphones, share of answers Answer Share Wear them (music, podcasts) 37% Could (social media, web, games) 31% Don't 32% Almost 70% already wear headphones on the way, or could.
2026So the pat can be heard as well as felt: a low pulse tone, made in code and not played from a file.
A pat, not an alarm
The idea came from Desmond Morris. In Intimate Behaviour he describes how a mother's repeated pat tells a baby there is no danger, the same kind of signal a bird gives with its head before it flies. “The repeated patting is therefore doubly soothing.” (Morris, D. (1997), Intimate Behaviour, New York: Kodansha America, p. 24.)
My 2020 sketch notes turned that into one line: the app pats you from time to time to say everything is OK, until it is time to fly. What changed in 2026 is what happens then. In 2020 it warned you vigorously. Now it says “Time to fly.” and waits for “I'm awake”.
The 2020 flow asked for sound and haptics “simultaneously and synchronized”. In the app one clock emits the beats, and haptics, sound and the orb follow the same emission, so they cannot drift. The sound is made in code, so there are no audio files. The phases change the feel, not only the words: resting is soft, nearing is firmer and about 15% faster, and arriving is a rising pulse with two knocks every two seconds until the rider taps “I'm awake”. The wake ignores the rider's soft settings on purpose. Hear it plays one bar here, made the way the app makes it.
Two sheets change the feel mid-ride. Haptics can only be felt on a real iPhone, and I have not verified them on one yet.


On the first run the pat is felt before the first ride, from the second card.
First run




The ride home
The demo ride is Home after the night shift: metro 52 from Zuid to Noord under the IJ, a four-minute change, then bus 34 to Grootzeil. Twenty-six minutes, one change, ten stops. Three rules place the phases. The first minute is always calm. Nearing starts when the stops to go reach the rider's wake distance, one to three stops. Arriving starts 45 seconds before the destination, and only “I'm awake” ends it. Underground, the copy says what the app is doing: “Underground. Counting stops by motion.” In this build that is simulated too.
Home after the night shift
Zuid → Grootzeil · 26 min · 1 change · 10 stops
Drawn by stops, not minutes. Dotted where the metro runs underground.
- Metro 52 7 stops · 17 min
- Change 4 min
- Bus 34 3 stops
- Zuid
- Europaplein, underground
- De Pijp, underground
- Vijzelgracht, underground
- Rokin, underground
- Centraal Station, underground
- Noorderpark
- Noord
- Station Noord
- G.J. Scheurleerweg
- Oosterlengte
- Grootzeil
- Settling, resting pat
- Resting, resting pat
- Underground, resting pat
- Resting, resting pat
- Transfer, nearing, firmer
- Resting, resting pat
- Nearing, nearing, firmer
- Arriving, the wake
- Arrived, the wake
- Resting pat
- Nearing, firmer
- The wake
- Settling
- The first minute is always calm.
- Nearing
- Starts 2 stops before Grootzeil, the wake distance on this ride.
- Arriving
- Starts 45 seconds before the stop. Only “I'm awake” ends it.
Calm, on purpose
The design system is a set of refusals. Matte paper, one primary action per screen, one slow curve with no bounce. No gradients, no drop shadows. Liquid Glass only on the two controls that float over the map. New York for display, SF Pro for the interface, Dynamic Type text styles only. If a screen feels busy, something is removed.
Contrast is a test, not an intention: ink at least 7:1 on paper, secondary text and line chips at least 4.5:1. Two values failed when measured and were changed. Both are on the palette below.
- paper#F2EFE1Background
- paperDeep#E8E4D3Cards
- brand#4B5D7EThe icon's ink: orb, route line, primary button5.8:1 on paper
- ink#3D4C70Text7.4:1 on paper6.7:1 on paperDeep
- inkSoft#59637FSecondary text5.2:1 on paper4.7:1 on paperDeep
- glow#D8A866Warmth, nearing and arriving only
- rest#8FA28ARested
- night#0A0D14Eyes closed
- paper#141A2ABackground
- paperDeep#1C2438Cards
- brand#A9B8DAThe icon's ink: orb, route line, primary button8.7:1 on paper
- ink#ECE7D8Text14.0:1 on paper12.5:1 on paperDeep
- inkSoft#A7B0CCSecondary text8.0:1 on paper7.2:1 on paperDeep
- glow#E2B878Warmth, nearing and arriving only
- rest#9DB39ARested
- night#0A0D14Eyes closed
Two corrections, after measuring
inkSoft, secondary text on a card
Zuid → Grootzeil · 26 min · 1 change, #5F6A88 · 4.2:1, under AAZuid → Grootzeil · 26 min · 1 change#59637F · 4.7:1Line chips on a card
Metro 52, Paper on solid · 2.9:1Bus 34, Paper on solid · 2.2:1Metro 52Ink on a 30% tint · 5.2:1Bus 34Ink on a 30% tint · 5.5:1
Light and dark on every screen, both from the same tokens.

Light 
Dark 
Light 
Dark 
Light 
Dark
Rest counts the minutes a rider actually rested: settling, resting and underground, never the change or the wake. Moments are noticed, never scored: a first ride, a first rest underground, ten rides. Every ride shown here is seeded demo data, and each screen says so.


Accessibility was part of done: VoiceOver throughout, phase changes announced, Reduce Motion turning pulses into opacity, and Eyes closed keeping the screen on because haptics only play in the foreground.
What is simulated
- Every ride. No location, no sensors. A pure ride model lays the route out in ride time, so a ride lasts exactly the minutes on its card, and a test runs one at 6000× in under a second.
- Underground. The app counts stops by motion in the copy only.
- Amsterdam. Station names and line numbers only. Line order checked against GVB's 2026 network, stops from OpenStreetMap, durations computed. No operator is involved.
- Two switches. Let Soothe learn it and Start with headphones are mocks, and their captions say so.
- The history. Seeded into an empty store so the charts are never empty. It is not user data.
- Haptics are not verified on hardware. The Live Activity and the Siri intent have not been checked by eye.
- No one has used it. No users, no store listing, no research since 2020.
How it was built
Claude Code built it, one step per session, over two days in September 2026. AGENTS.md is the contract every session reads first: the non-negotiables, the workflow, and a router that names the one doc to read for the area being touched. The kickoff prompt is one line: read AGENTS.md and do the next step. A step is done only when it builds, its tests pass and its docs are current. Then the agent stops. It never commits its own step. Starting the next session is my approval of the last one.
- S0. Scaffold: the agent docs, the XcodeGen project, a Makefile, the icon and an empty three-tab shell.
- S1. Design system: tokens, components and a hidden gallery.
- S2. Amsterdam data and routes: the catalog, SwiftData, the seeder, Today, route detail and New route.
- S3. Feel engine: the rhythm clock, haptics, the procedural soundscape, the Sound and Touch sheets.
- S4. Journey: the simulator, map and timeline, the orb, the change, underground and the wake.
- S5. After the ride: the summary, Rest, Moments and seeded history.
- S6. Onboarding, You, the Live Activity with Dynamic Island, and the Start my ride home intent.
- S7. Polish: dark mode, Dynamic Type, VoiceOver, Reduce Motion, empty states, copy and screenshots.
Apple frameworks only, no third-party dependencies: 133 Swift files, about 7,050 lines of app code and 2,290 of tests, 205 tests passing, no warnings.
This page was made the same way, one step per session, and I read every word before it landed.
More case studies

AI Flashcards
A short-term vision for the flashcards in Studocu AI: a deck made from a student's own sources, one rating per card, and a deck that says what to study next.
case study · 2025 · read it
Course Chat
The take-home that got me hired at Studocu in 2022: a live chat with voice rooms on the course page, chosen after asking students what they already do.
case study · 2022 · read it
Strapi Marketplace
Strapi's design assessment, April 2022: a plugin marketplace for its admin where a developer sees who made a plugin and what others think before installing it.
case study · 2022 · read it