DEV Community

TAMSIV
TAMSIV

Posted on

I Rewrote 3 Detail Screens to Make Them Look Identical — Here's Why That 40-Commit Sprint Was Worth It

40 commits in 3 days. Zero new features. Just three detail screens rewritten to look identical.

Yes, that sounds absurd when you're shipping solo and every hour matters. But after 6 months of building TAMSIV (a voice-powered task manager), I've learned that the work nobody notices is often the work that keeps an app installed.

Here's what I did, why I did it, and what changed in the codebase.

The problem

TAMSIV has three "detail" screens: Task, Memo, Event. They all show roughly the same things:

  • Title and status
  • Who has access (owner + shared groups)
  • Parent folder in the hierarchy
  • Tags
  • Main content
  • Reminders, attachments, activity log

Each one was built at a different point in the project. Each evolved its own layout, its own section order, its own variants for the same data. Opening a task felt fine. Opening a memo right after felt subtly off. Opening an event after that felt like a third app entirely.

Nobody complained explicitly. That was the clue. Users don't complain about inconsistency — they just get tired and close the app.

Step 1: extract the access tree

The hardest piece was rendering "who can see this". Before the refactor, each screen answered that question differently:

  • TaskDetail showed an assigned-folder card plus a small "assigned to X" badge
  • MemoDetail showed a flat list of group members
  • EventDetail had a detached "Participants" section

I extracted a new component TaskAccessTree with two branches:

<TaskAccessTree
  ownerId={item.owner_id}
  sharedGroups={sharedGroupsWithMembers}
/>
// → Branch 1: owner (avatar + name)
// → Branch 2: each shared group with stacked member avatars
Enter fullscreen mode Exit fullscreen mode

Same component, three screens, zero ambiguity. Users can now tell at a glance who sees a piece of content without reading a line of text.

Step 2: hide empty breadcrumbs

The parent-folder breadcrumb (e.g. Family > Shopping > Supermarket) rendered even when the task was at the root. That left a ghost arrow hanging before the title.

// Before
<Breadcrumb parents={parents} />  // rendered "› › › Title" when parents = []

// After
{parents.length > 0 && <Breadcrumb parents={parents} />}
Enter fullscreen mode Exit fullscreen mode

Two lines. One visual bug gone. An empty space transformed into breathing room.

Step 3: #-prefixed tags under a header

Tags used to render as a flat row of words, indistinguishable from body text:

urgent groceries weekend family meals
Enter fullscreen mode Exit fullscreen mode

Now:

<Section title="Tags">
  {tags.map(t => <Chip key={t}># {t}</Chip>)}
</Section>
Enter fullscreen mode Exit fullscreen mode

A clear header, a universal prefix convention. Users recognize tags instantly instead of scanning for them.

Step 4: same section order, everywhere

After refactoring the individual pieces, I enforced a single section order across all three screens:

  1. Title and status (or date for events)
  2. Access tree (TaskAccessTree)
  3. Parent folder assigned
  4. Tags
  5. Main content (description / memo body / event details)
  6. Reminders and recurrence
  7. Attachments
  8. Activity log

The benefit isn't just visual. It drastically reduces the cost of adding a new cross-cutting feature. When I eventually add, say, an "AI summary" or "auto-translated version" section, I code it once and drop it in position 5. All three screens inherit it.

Before, that same feature would have needed three implementations with three position negotiations.

Step 5: extract GroupMembersSection

When content is shared in a group, we need to show which members of that group can actually see it (there are fine-grained permissions). This rendering existed in three slightly different forms across the screens.

I collapsed them into a single component:

<GroupMembersSection
  groupId={group.id}
  visibleMembers={membersWithAccess}
  greyedMembers={membersWithoutAccess}
  tapToSelect={canEdit}
/>
Enter fullscreen mode Exit fullscreen mode

Re-used in TaskDetail, MemoDetail, EventDetail, and also in the "Select users to share with" modal. Four callers, one component.

The real benefit: future features now cost 1/3

Here's what sold me on spending 3 days on this.

In the last 6 months, every new feature that touched multiple detail screens took 3x the dev time it should have, because I was reconciling 3 different layouts every time. Reminders, attachments, activity logs, comments, reactions — all of it cost me tax.

Now each new feature drops into one shared layout. I've already measured the effect on the next two features (an inline translation banner and a "recently viewed by" section) — they took a single afternoon each, down from an estimated day-and-a-half before.

Refactors don't just pay for themselves in user experience. They pay for themselves in velocity.

Bonus: 22 SEO redirects

In parallel, I fixed a 22-slug SEO mess on the marketing site. Early translation passes had left obsolete slugs in DE/ES/IT/PT that returned 404s on Google. Each old slug now redirects (301) to its current version, and x-default hreflang is corrected so search engines know the canonical version.

22 visitor paths recovered instead of lost. A good reminder that invisible work isn't only inside the app — it's everywhere your users don't see.

Takeaways

  1. Consistency is invisible value. Nobody says "thanks for the matching section order", but everybody feels when it's there.
  2. Component extraction follows usage, not anticipation. I waited until the same rendering lived in 3+ screens before extracting. Earlier would have been premature.
  3. Refactors unlock velocity. The cost is now. The payoff is every feature after.

TAMSIV is live on the Play Store (Android, free, 6 languages). 780+ commits, still solo. Full write-up of this sprint is on the blog.

What's a refactor you shipped that users never noticed but that changed how you build?

Top comments (0)