Case Study — Atom

An app that tracks it all

A single place for tracking meals, workouts, and health metrics.

Role

Design + iOS build

Timeline

72 Hours

Scope

IA, iOS Build, Design System & UI

Stack

SwiftUI · SwiftData · HealthKit · Claude API

nucleus-hero — hero device mockup, dark + light nucleus-hero — hero device mockup, dark + light [media: nucleus-hero — hero device mockup, dark + light]

What it does.

Planning

I'm a designer, so the instinct was to open a canvas and start drawing screens. I didn't. I started with what the app had to do — what data it would hold, how food, workouts, and health connected, and how many tabs it needed to make sense. The look of it could wait. It waited until the very end.

The data model

Food entries, workout logs, and a daily health snapshot — and the relationships between them. Getting this right first meant the features had something solid to stand on.

Information architecture

I mapped the app to tabs before any of them existed. I planned for four. Building it would later teach me it needed six.

Function over form

The hardest discipline as a designer: deciding, on purpose, that nothing would be styled until it actually worked. No colours, no polish — just structure.

nucleus-planning-data — the data model nucleus-planning-data — the data model [media: nucleus-planning-data — the data model]
nucleus-planning-ia — information architecture nucleus-planning-ia — information architecture [media: nucleus-planning-ia — information architecture]
nucleus-planning-form — function over form nucleus-planning-form — function over form [media: nucleus-planning-form — function over form]

The Biggest Challenge (at the time)

I had never written a line of Swift or opened Xcode. So I did the only thing I could: I asked Claude for every step — create the project, add a screen, wire up the data. The first twenty-four hours were shockingly smooth. Everything I asked for worked. None of the buggy iOS horror stories I'd been warned about showed up.

Claude as the manual

From "make a new project" onward, every step came from asking. I wasn't writing code so much as directing it and reading the result.

A smooth start

A day in, the core app ran on my phone. No fighting the toolchain, no cryptic errors — it just worked, which felt almost too easy.

Seeing only the surface

I could see what Claude was building, but not how. The architecture underneath was its decision, and I trusted it without understanding it. That came back to bite me.

nucleus-firstday-manual — Claude as the manual nucleus-firstday-manual — Claude as the manual [media: nucleus-firstday-manual — Claude as the manual]
nucleus-firstday-smooth — a smooth start nucleus-firstday-smooth — a smooth start [media: nucleus-firstday-smooth — a smooth start]
nucleus-firstday-surface — seeing only the surface nucleus-firstday-surface — seeing only the surface [media: nucleus-firstday-surface — seeing only the surface]

Functionality First

With the skeleton running, I built the features I actually wanted — the parts that made Nucleus worth using over the four apps it was replacing. Still no real styling. Just getting each thing to work, then moving to the next.

The food tab

Type a meal in plain language and Claude estimates calories and protein, or snap a label and it reads the panel. Meal type auto-selects by time of day; duplicates collapse into one row with a ×N badge.

The morning briefing

Overnight Apple Watch data — HRV, sleep, strain — run through Claude into a fixed four-line briefing, every number a tappable chip into its 30-day trend.

Bugs were part of building

A camera that presented itself eight times at once. A keyboard with four "Done" buttons stacked side by side. Each one taught me a little more about how the framework actually behaves.

nucleus-build-food — the food tab nucleus-build-food — the food tab [media: nucleus-build-food — the food tab]
nucleus-build-briefing — the morning briefing nucleus-build-briefing — the morning briefing [media: nucleus-build-briefing — the morning briefing]
nucleus-build-bugs — bugs were part of building nucleus-build-bugs — bugs were part of building [media: nucleus-build-bugs — bugs were part of building]

The BIGGEST Challenge

The smoothness didn't last. As I loaded real data, the app began to slow and freeze. The architecture Claude had chosen ran fine on a handful of records — but it buckled under mine. I'd been shipping code I couldn't see into, and now I had to understand it. I asked Claude to explain it in plain language, and the problems turned out to be simple once I could read them.

Everything on the main thread

Work that should have run in the background was happening right where the screen draws — so the interface froze while it churned.

Reading the database on every tap

The app re-read its entire store on every click instead of remembering what it already knew. At scale, that meant thousands of reads for a single tap.

Fixed one by one — functional in two days

Move the heavy work off the main thread. Cache what was being re-read. Only recompute when something actually changes. Two full days after I opened Xcode for the first time, the app was fully functional — and fast.

nucleus-wall-thread — everything on the main thread nucleus-wall-thread — everything on the main thread [media: nucleus-wall-thread — everything on the main thread]
nucleus-wall-reads — reading the database on every tap nucleus-wall-reads — reading the database on every tap [media: nucleus-wall-reads — reading the database on every tap]
nucleus-wall-fixed — fixed one by one nucleus-wall-fixed — fixed one by one [media: nucleus-wall-fixed — fixed one by one]

Finally, UI.

With the app working and fast, I finally did the thing I'd been holding back: I designed it. Building for myself, I had a clear point of view — this should feel like an instrument, not a wellness toy. Dark, dense, numeric. Colour only ever means state. I built the design system last, once the app had earned it.

Tokens

A dark-first ink scale from a near-black background up to high-contrast text. Colour reserved for signal — strain, PR, trend up, trend down, recovery — over a six-colour key per muscle group. Every value a token, mapped one-to-one into SwiftUI.

Typography

Two faces, both chosen so figures read cleanly: Space Grotesk for display and headings, JetBrains Mono for every number, weight, and timer. Deliberately not the iOS default.

Components

Metric cards with a PR state, the badge-and-pill system, the session card, the set-logger row built like a precision instrument, sparklines and a hero volume chart, progress rings — and a four-tab mockup to prove it all composes.

nucleus-ds-tokens — token grid nucleus-ds-tokens — token grid [media: nucleus-ds-tokens — token grid]
nucleus-ds-type — type scale nucleus-ds-type — type scale [media: nucleus-ds-type — type scale]
nucleus-ds-components — component grid nucleus-ds-components — component grid [media: nucleus-ds-components — component grid]

A full-blown app. One user.

Nucleus shipped to one user — me — and it's the app I open every morning. The plan said four tabs; building it taught me it needed six. Trends and Settings each turned out to need a home of their own, a lesson the mockups could never have given me. As a designer who'd never coded, I learned that the structure has to survive contact with real data before the surface is worth touching. Next: logging workouts by conversation, an Exercise Effort Index that ties Apple Watch heart-rate to specific lifts, and the full Trends tab.

nucleus-final — the shipped app, six tabs, dark + light nucleus-final — the shipped app, six tabs, dark + light [media: nucleus-final — the shipped app, six tabs, dark + light]

The app I shipped isn't the one I imagined.

Constraints are the real design brief.

When you build for one user — yourself — the constraints are as simple as they get. One device, one set of habits, one history of data. Even then, I cut features I had planned, simplified screens I had drawn, and made dozens of compromises between what would be interesting and what I could actually make work. Now imagine building for the public. Every constraint multiplies. The shortcuts that worked because I know my own data disappear. Nucleus taught me that planning is unlimited. Shipping is not. The work is mostly deciding what not to build.

AI does exactly what you ask. That's the problem.

The first day was smooth because the requests were simple. As the app grew, vague prompts produced code that looked right and behaved wrong — confident, complete, and subtly broken in ways I couldn't see until real data hit it. Learning to work with AI meant learning to kill ambiguity before sending a single word: what exactly do I want, what should it never do, what does success look like. A well-formed question gets a useful answer. A lazy one gets a plausible-sounding guess.

Prompting is a skill, and it compounds.

By the end, I wasn't just describing features — I was describing constraints, edge cases, the data model, the performance budget, and the failure mode, all before asking for any code. Each session I got better at it. That precision is what turned a two-day build into something that actually runs fast on real data. It's also what I'd carry into any AI-assisted product work: the output is only as clear as the input.

Nucleus is the smallest version of a product problem. I'd like to solve a bigger one.

View more projects

MKU Website Redesign · Sales Pro

Browse projects

Explore the blog

60 Minutes to Ship: How a Sleeping TV Sparked a Better Event Experience

Read posts