Case study 01 · Designed & built

Foxed

Your reading, well-loved.

A fic-and-book tracker for readers who live on AO3, designed and built solo, end to end, with Claude Code as an implementation partner. Four months, 141 commits, one very opinionated idea about what a reading app should feel like.

Role
Product design & solo development
Timeline
Jul – Nov 2026, ongoing
Tools
Expo / React Native, on-device SQLite, Claude Code
Deliverables
iOS app (private beta), design system
141
Commits
~4 mo
Timeline
Solo
Team
iOS
Platform
9
Themes
0
Servers
Foxed, an iOS app. Headline: “Your reading, well-loved.” Three phones show a fic detail screen with reading progress, the Home screen with Currently Reading, Waiting on Update and Nightstand sections, and a yearly recap reading “8.4M words this year.”

The 30-second version

The problem

Readers who live on AO3 track progress across tabs, bookmarks and memory, and no tool treats a fic and a book as the same kind of finished.

What I did

Designed and built an iOS tracker with no accounts, no servers and no hosted story content, around one status model and a design system decided up front.

The result

In private beta on TestFlight with a handful of friends. Five decisions, below, shaped what it is.

01 · The problem

Nobody treats a fic and a book as the same kind of finished.

Readers who live on Archive of Our Own track progress across browser tabs, bookmarks, and memory. Readers who track books use Goodreads or StoryGraph. Nobody who does both gets to treat “I finished this” as one feeling, because no tool treats fic and prose as the same category of thing, even though emotionally they are.

Worse, most tools that touch AO3 at all do it carelessly: scraping full story text, building a competing reading surface, or quietly forgetting that hits, kudos, and comments are how fan authors are paid.

Foxed starts from a constraint, not a feature list. Design the whole product around what’s left once you take these off the table:

  • Never host a word of story content.
  • Never require an account.
  • Never run a server.
The About Foxed screen. A card reads “Made by a fan, for fans: Foxed is your bookshelf, not a reading app. It doesn’t host, copy, or display any stories.” A second card reads “Your data stays here: no accounts, no servers, no analytics, no ads.”
The three constraints, in the app’s own words.
A fic detail screen for a sample story, “salt & honey.” It shows a generated cover, word count, a progress card with a “View on AO3” button, and the note “Reading happens on AO3. Authors see your hits and kudos.” Status and shelf controls sit below.
Reading happens on AO3, so authors get every hit and kudos.
A sheet over the fic detail reading “You’re all caught up. All 12 chapters read, the rest is up to Mystery_author,” with the buttons Mark as Waiting on update and Keep it in Reading.
Caught up on a work in progress isn’t finished. It’s waiting on the author.

02 · Design system

A system decided before a single screen was drawn

Foxed is built against one living reference doc (colors, type, iconography and voice) that has been revised more often than any individual screen. These are excerpts from the real thing, not a reconstruction for this write-up.

Palette: warm alphas only, never flat gray

Ink base
#171310

App background

Rust
#C06A38

Primary actions, fic strip

Amber
#D9A84E

Streaks, warnings, gold moments

Moss
#8A8A5C

Books, toggles-on

Parchment
#EFE6CF

Generated covers

Cream
#F6F0E3

Text, via alphas

Type: two roles, never mixed

Display
Serif, for greetings and quiet moments of voice
Buttons & emphasis
Karla, 700
Body & rows
Karla, 400, cream at 85%
Overline labels
Tracked +14%

Voice

Warm, bookish, lightly foxy. Honest about AO3: reading happens on AO3, authors see your hits and kudos. Never corporate, never gamified-pushy, no exclamation-point pileups.
  • “Here’s what the fox dragged in.”
  • “Resting to stay under AO3’s radar.”
  • “Your shelf is waiting.”

Icons & motion

  • 24×24 grid, 2px stroke, round caps, exactly one rust accent per icon.
  • No emoji glyphs in UI chrome (user content like shelf names is exempt).
  • Quiet, paper-like motion: fade plus a 4–6px slide, 200–300ms ease.
  • No bounces, no confetti. Haptics on status changes and streak moments only.

03 · Key decisions

The choices that actually shaped the product

Not a feature tour. These are the handful of calls where the obvious, easy version of the idea was wrong, and the real one took more nerve.

The Nightstand cap

Scarcity as a feature, not a limitation

Problem

A “To Read” list is where good intentions go to die. Nothing stops it from growing to 400 items, and an infinite list applies zero pressure to actually choose.

Approach

Split “To Read” into two shelves: a capacity-limited Nightstand (your real next-up queue: 8 by default, adjustable from 4 to 12) and a looser Shelf for “maybe someday.” Add a ninth book to a full Nightstand and nothing silently succeeds. A swap sheet opens, asking what comes off before the new one goes on.

Outcome

The decision happens at the cheapest possible moment, when adding one thing, instead of later, staring at an unmanageable pile. It also surfaced real engineering edge cases worth naming: a modal-presentation race that could silently swallow the swap sheet, and a capacity-check race when two adds landed in the same instant. Committing to a constraint meaning something is what made those bugs visible at all.

A fic detail screen for a sample story, “A well loved fanfiction,” sitting on The Shelf. A progress card shows Chapter 3, 25%. The status card offers Nightstand or The Shelf, with the line “The Nook: the maybe pile, unsure reads and stray tabs.”
Two shelves: the Nightstand for next up, The Shelf for maybe someday.
A bottom sheet titled “The Nightstand is full.” It shows the fic moving in and a list of four items that could go back on the Shelf, with Make the swap and Leave it on the Shelf buttons.
Adding to a full Nightstand opens a swap, not a silent success.
The My Library screen filtered to To Read, with Nightstand selected. The line “You already said yes to these, no debate, just next in line” sits above two reorderable cards, one ebook and one fic, each at 0%.
The Nightstand in the Library: “You already said yes to these.”

The Companion

A notes space that can’t spoil you

Problem

Long, multi-work series are exactly where readers want a running notes space, and exactly where showing the wrong thing at the wrong time does real damage.

Approach

Every note, fact and connection in the Companion is stamped with the series position it was written at. The page only ever reveals what’s at or before wherever the reader currently stands, with no manual spoiler tagging. Categories aren’t pre-defined either: the app notices a reader has been tracking “characters” or “places” as the notes accumulate, instead of handing over empty buckets labeled in advance.

Outcome

A notes feature that works while a series is still unfolding, not only in hindsight after it’s finished. That is the harder and more useful version of the idea.

The Companion for Throne of Glass. A dark header reads “Reading with you, Book 2, page 120. Everything here stops where you are.” Below are a search field, an Add a thing button, and lists of characters, locations and glossary entries.
The header says it plainly: everything here stops where you are.
A character page: facts under “What you know,” connections to two other characters with short notes, and a personal margin note stamped Book 1, page 300.
Facts, connections and margin notes, each stamped with where you were when you wrote it.

The celebration economy

Rewarding without nagging

Problem

Most reading-tracker gamification (streak flames, badge walls, reading challenges) reads as warm for a week and naggy for the rest of the year.

Approach

Every reward moment is tiered deliberately, by how often it should happen. Daily streaks stay almost silent: a calendar mark, with a “pressed leaf” forgiving one missed day automatically. Wax-seal achievements are rare and get the one genuinely animated moment in the whole app. A yearly Recap, in the style of a music-streaming “wrapped,” is the single big annual event. Nothing competes for the same moment twice.

Outcome

A reward system with a point of view about restraint, and a system that made room to remove a tier that wasn’t earning its place (see the last decision).

A bottom sheet over a fic page: a terracotta wax seal with a flame, the label “A seal, pressed,” the title “Slow Burn Survivor,” and the line “198,000 words. You saw it all the way through.” above a Lovely button.
A seal, pressed: rare, quiet, and the one animated moment in the app.
The Your year screen: 321k words read this year, a twelve-day streak shown as a row of dots, a progress bar toward a 1.0M-word goal, a monthly bar chart, and a row of seven wax seals with one earned.
Your year: the streak is a row of dots, and seals fill in slowly.
The November recap. Three stat cards show 0 finished, 235k words and 10 days read. A week-by-week bar chart is followed by the line “The 8 to 14 stretch was where November really happened,” and a list of four fics still being read with their word counts this month.
A month with nothing finished still gets a real story, not an empty card.

Reading Focus

One switch, not a settings maze

Problem

A reader who only tracks books doesn’t care about fandoms, ships, AO3 ratings or update alerts. The obvious fix, ten individual toggles, is its own kind of broken: a settings screen nobody actually goes and tunes.

Approach

Reading Focus is a single switch. Flip it, and every AO3- and fic-specific surface across the entire app disappears at once: filters, stat cards, the favorite-tags widget, the AO3 footer link, the Waiting status. Flip it back and nothing was lost. It was all just hidden, not deleted.

Outcome

The inverse of feature-flag sprawl: one well-placed decision point instead of a dozen half-measures scattered through the app.

The AO3 & Library settings screen. Under Reading Focus, two choices: Fic & books, selected, and Books only. Below are the AO3 account, blocked tags and following sections.
Two plain choices, with the effect explained in one sentence.
The Foxed Home screen with Fic & books on. A banner says AO3 looks like it is down right now. Below Currently Reading is a Waiting on Update shelf with two fics, then the Nightstand.
Fic & books: AO3 status and a Waiting on Update shelf.
The same Home screen with Books only on. The AO3 banner and the Waiting on Update shelf are gone, leaving Currently Reading, the Nightstand and the Shelf.
Books only: the same screen, with every AO3 and fic surface gone.

Cutting the Ink Cellar

Killing a feature without deleting it

Problem

A word-count ritual, an “ink bottle” that fills as you read and corks at a milestone, collected in an “Ink Cellar,” shipped, got real use, and still didn’t feel load-bearing. It was competing for attention with the celebration moments that mattered more.

Approach

Instead of ripping it out, along with the data model, achievements and backup fields that had grown up around it, it got hidden behind a single feature flag. Every entry point (a Stats card, a celebration sheet, a Field Guide entry, a month-recap link) was gated off in one place, while the underlying word tracking kept running quietly underneath.

Outcome

Cutting a feature doesn’t have to mean deciding its fate forever, or throwing away data a reader already built up. If it’s ever worth a second look, flipping the flag back on picks up exactly where it left off.

The Blind Date with a Story screen: a wrapped parcel tied with a green ribbon and a tag reading “an evening, a fandom you’ve read before, domestic,” with mood chips above and an Unwrap it button below.
Blind Date with a Story: a gift-wrapped pick from your own Waiting list.
The first-run welcome sheet, “Welcome to Foxed,” over the Home screen. Three points: your bookshelf, not a reading app; everything stays on your phone; unofficial, and proudly so. A Start shelving button sits below.
First run: three honest sentences, including that nothing leaves your phone.
The first onboarding screen: a book icon and a small heart above “Track every fic and book,” with a Next button and four progress dots.
Onboarding starts with one idea per screen.

04 · Process

Built solo, with Claude Code as the implementation partner

Every product call (what to build, what voice it should speak in, what to cut, what actually ships) was mine. Claude Code wrote most of the code, under close, continuous review, across roughly 140 incremental commits over four months.

  1. One screen at a time, tested on a real device

    Nothing shipped on faith. Every change was read, built, and actually used on a physical phone before it got pushed. The working rhythm was build, test, “push it,” never the reverse.

  2. Bugs get fixed as a class, not a case

    When one modal-presentation race turned up, the fix wasn’t just that one screen. It was auditing every root-mounted sheet in the app for the same mistake, and fixing every instance found in the same pass. The same discipline applied to a timezone bug in streak math and a stale-tier bug in the Nightstand logic.

  3. Privacy as an engineering constraint, not a policy page

    No accounts, no servers, and, deliberately, zero analytics or crash reporting. That tradeoff is real: it means a hand-run manual QA checklist is the only thing standing between a broken build and a friend’s phone, run in full before every share.

  4. One living design doc, not tribal knowledge

    Color, type, iconography and voice all live in a single reference file that every session gets pointed at first. A new screen gets built against the system, not improvised and reconciled later.

05 · Outcomes

What shipped, and what’s honestly still early

  • Fic + book trackingOne status model, one celebration system, for both
  • AO3 importBookmarks, series, and author/series following
  • Goodreads & CSV importWith duplicate detection across and within files
  • The CompanionSpoiler-safe notes wiki, per series
  • Nightstand & ShelfA deliberately capacity-limited queue
  • Background update checksReal notifications, opt-in, tied to the moment it matters
  • 9 themes, 2 type pairsIncluding a true-black “Candlelight” mode
  • Demo ModeShow the app without exposing a real library

Honestly: Foxed is in private beta, shared with a handful of friends via TestFlight. This isn’t a growth story with a user count worth bragging about. It’s a depth-of-craft one. The goal was never scale; it was building something specific and well-loved for people who actually live in this niche, including myself.