Yangming Li
Featured Interactive Experience

Focus Room

Not another timer. A room you return to.

Built to reduce friction before focus, with soft entry, low-visibility controls, and a room that settles deeper as the session unfolds.

5ambient layers Localpersistence Ghostcontrols Sessionevolution

Soft entry, low-visibility controls, and session-based atmosphere optimized for calm, not feature density.

Focus Room

A quiet room for deep work.

Hover wakes the room. Hold to step inside.

Interactive Preview Hover wakes rain Hold to enter
8s room cycle
Room settling
Prototype

Main Room

The room remains the hero. Controls stay near-silent until invited back into view, while the atmosphere deepens slowly enough to feel alive without behaving like a dashboard.

Session star collected. The wall keeps a soft trace of finished work.
Focus Timer
25:00
Ready
Ambient Layers
Piano42% Rain58% Brown34% Cafe18% White12%
Session Complete

Good work. Take a breath.

Architecture

Technical credibility, surfaced with less weight

The prototype still reads like a real SwiftUI handoff, but the first scan starts with the four decisions that make the experience believable: orchestration, persistence, audio seams, and reusable views.

Orchestration AppState + ViewModel

One observable root owns dependencies while a single room view model drives entry, timer, ghost UI, and completion.

Persistence Local by design

Sound selections, volumes, and last duration persist through a small UserDefaults seam without introducing account friction.

Audio Mockable playback seam

The prototype stays visually honest while deferring real fade-aware audio layering until the next phase.

Views Reusable composition

Threshold, room, timer, mixer, background, and completion remain isolated enough to move directly into an app target.

System Shape

One orchestrator, small seams, reusable views

The architecture keeps interaction quality central. State lives in one place, derived atmosphere values keep visuals coherent, and services stay thin enough to swap without rewriting the room.

FocusRoomApp
`-- AppState
`-- FocusRoomViewModel
|-- ThresholdView
|-- FocusRoomView
|-- RoomBackgroundView
|-- FocusTimerView
|-- AmbientMixerView
`-- SessionCompletionView
AppState / ViewModel orchestration Single source of truth for phase, timer, mixer, and room atmosphere.

AppState owns dependencies. FocusRoomViewModel centralizes threshold entry, session timing, ghost UI idling, completion messaging, and derived room evolution so the visuals never feel bolted together.

Entry ritual, idle fade, and completion share one mental model instead of scattering state across views. Derived RoomAtmosphere values keep lamp warmth, rain depth, and background calm in sync.
Local persistence Preferences survive without login or backend ceremony.

FocusRoomPreferencesStoring isolates persistence behind a protocol, so the room can remember last-used sound layers and duration while keeping countdown runtime state ephemeral.

UserDefaultsPreferencesStore is production-friendly for a first version. InMemoryPreferencesStore keeps previews and local iteration fast.
Mock audio seam Visual and interaction quality can mature before real assets land.

The audio layer is intentionally abstracted behind AmbientAudioControlling. That keeps the prototype believable today and ready for fade-aware playback tomorrow.

Preview fade-in and session completion fade-out can later map to real audio without redesigning the interface. The mock engine preserves product behavior while avoiding placeholder asset debt.
Reusable view structure Each layer is scoped tightly enough to migrate into Xcode cleanly.

The UI is split into the same components a production app would want: threshold ritual, background composition, timer, mixer, and completion. The room stays primary because each piece knows its role.

GhostGlassPanel standardizes the low-visibility control language. Preview data and theme tokens support iteration without turning the project into a demo-only codebase.
Source

Start with the code that makes the prototype believable

Rather than giving every file equal weight, the page starts with the two seams that matter most on first read: the room orchestrator and the local persistence layer. The full browser is still here when you want the whole tree.

swiftui-prototype/ViewModels/FocusRoomViewModel.swift Loading
Loading source...