Bandmakers — the polish pass

Every screen measured against the Apple design skill and the researched industry standards. What changed, what rule it broke, and why it is better.

These are renders, not photographs of the running app. Every colour and size below is read straight out of src/theme.ts at build time, so they cannot drift from the real values — but they are re-creations. The real thing still has to be judged on a device. The simulator was 95% set up tonight and is blocked on one command needing your password; see the end of this page.

The texture was being used as wallpaper

apple-design §15 · hierarchy from weight + size + leading — not from repeating one style

Space Mono caps was on 113 places plus all 44 buttons — weekdays, durations, ticket counts, statuses, every button in both apps. theme.ts already said “use sparingly… section labels only”; the code did the opposite. A strong texture repeated everywhere stops reading as character and starts reading as a template. It is now on 54 places, all of them genuine section headings.

Before

Winter concert

Winter Concert
Open to everyone   0/80 tickets   EGP 150
Rehearsals, materials & more
Move to closed
After

Winter concert

Winter Concert
Open to everyone
0 of 80 tickets  ·  EGP 150
Move to closed

Numbers were a grid of boxes

dataviz · a boxed tile grid is the stock dashboard look; rows let values line up

Four bordered tiles in a 2×2 all fight for attention, so nothing reads as more important than anything else. As rows, the labels line up in one column and the figures in another, so they can actually be compared — and the money section now leads with one headline figure instead of four of equal weight.

Before

Money

EGP 41,384
Taken, last 30 days
EGP 5,079
Tax within that
EGP 0
Owed to the academy
EGP 38,634
This month
After

Money

EGP 41,384
Taken, last 30 days
7 payments
Tax within that
EGP 5,079
Owed to the academy
EGP 0
This month
EGP 38,634

Choosing something painted the row black

apple-design §16.4 familiarity · iOS marks a choice, it does not repaint it

The selected row inverted to solid ink. On a list of seven branches that is a full-width black bar shouting at you — and an inverted row is a spreadsheet highlight, not a considered choice. iOS picks with a checkmark and leaves the row alone; the weight change on the label carries the rest.

Before

Teacher rate

Core
Expert
Legacy
After

Teacher rate

Core
The standard rate
Expert
Costs more than Core
Legacy
Advanced students only

Me was doing two unrelated jobs

apple-design §16.6 simplicity · burying everything in one place looks minimal but is not simple

The staff Me tab was your profile and the console for running a music academy: identity, a wall of 41 permission words, then sixteen admin rows under three headings. Splitting them is the fix; restyling the same pile would not have been. Sixteen rows moved to their own screen, in five short groups — a group stops being scannable past about six rows.

Before

Me.

Run the academy

Concerts
Teachers
Timetable
Instruments
Day minimums
Closed days
Branches & check-in
Books
Books handed out
Stock

Money

Lesson prices
Bundles
Discount codes
After

Me.

D
Demo Owner
Owner · owner@example.test

The academy

Run the academy
What you can do
41

Account

Switch to my parent account
Signed in
Sign out of staff

Three sections, and only two looked alike

apple-design §16.4 familiarity · things that look the same must behave the same

Photos & clips had three parallel sections — but two were wrapped in a card and one was a bare button. It also never said whether you had any clips, so it failed wayfinding: a screen must answer “what’s there?”. And every heading repeated the button beneath it (YOUR PHOTO over Add a photo), which is the weak-mapping smell. It is a list of three things you can add, each with a state — so it is rows.

Before

Your photo

No photo yet.
Add a photo

Playing video

Nothing uploaded yet.
Upload a video

Performance clips

Add a clip
After
Photo
Not added
Playing video
Not added
Performance clips
None

A short video of you playing helps a teacher put you at the right level before your first lesson.

Text you could not properly read

WCAG 2.2 · 4.5:1 for body text — measured against every surface, not the easiest one

Contrast was calculated for every text colour against paper, card and paperDeep. Three failed: the grey under every name and hint at 3.25:1, the warning colour carrying “4 unpriced” at 3.54:1, and the yellow accent at 2.98:1 — failing even the large-text bar, so the word we chose to highlight was the least legible thing on screen. All now clear 4.5:1.

Before
Alan Samer
throughalanslens@gmail.com
Beginner
Lesson prices
4 unpriced

3.25:1 · 2.98:1 · 3.54:1 — all under the bar

After
Alan Samer
Beginner · throughalanslens@gmail.com
Lesson prices
4 unpriced

4.50:1 · 4.51:1 · 4.55:1 — all clear

What else changed

smaller fixes, same rules

Where this came from

two research passes, ~300 cited rules

Two agents spent the night reading primary sources — Apple HIG, Material 3, NN/g, WCAG, IBM Carbon, Baymard — and wrote 211 checkable standards rules and ~90 craft rules into _DESIGN/. Every rule is tagged [EVIDENCE] / [CONVENTION] / [OPINION] and cited, and both files are explicit about what could not be verified.

Genuine conflicts are flagged rather than papered over: touch targets 44 vs 48 vs 24, body leading 1.29× vs 1.5×, title case vs sentence case, one primary button vs one-or-two. Where we picked a side, the index says which and why.

What I could not do

honest limits

These are renders, not the running app. The colours and sizes are read from theme.ts at build time so they cannot drift, but they are re-creations.

The iOS simulator is now installed and working — the 8.46 GB runtime downloaded fine, the app boots and bundles, and simctl takes real screenshots. It is blocked on one command that needs your password:

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

Without it there is no way to tapsimctl has no input support, AppleScript is unavailable here, and CocoaPods is not installed so a native dev build cannot be made. Expo Go puts a first-run dev-menu sheet over the app that needs exactly one tap to dismiss; I tried five ways to suppress it and none worked. Run that one line and the next pass can screenshot and click through every screen for real.

Full detail: _DESIGN/SIMULATOR_BLOCKER.md.

The bug I would not have found by looking

RESEARCH_STANDARDS E14/E24 · loading must never be mistakable for empty

Two screens turned a dropped request into a confident false statement. Placing a make-up said “This teacher has no times at this branch.” and a gifted lesson said “No free times right now — ask the academy.” — when in fact the request had simply failed.

That matters here more than most apps: CLAUDE.md §7 records that this API resets roughly one request in three. So a desk person would have turned a parent away, or a parent would have chased the academy about a problem that did not exist. Both now say which of the three states they are actually in.
Before

Time

This teacher has no times at this branch.

…said after a failed request

After

Time

We couldn’t load their times. Pick the teacher again to retry.

…and “no times” only when there genuinely are none

The ten-step audit, run in full

from RESEARCH_STANDARDS.md

1 · Contrastevery text colour now ≥4.5:1 against all three surfaces
2 · Targetsevery tappable thing ≥44pt — verified by brace-matching each style block
3 · Dynamic Type⚠️ needs a device — but nothing disables font scaling anywhere
4 · Grouping3:1 between/within rhythm, now the same on tabs and pushed screens
5 · Hierarchyone filled button visible per screen (8 flagged, all mutually-exclusive states)
6 · States2 real bugs fixed — failure rendered as fact
7 · Latencynothing under 1s, per NN/g
8 · Motion120 / 200 / 320ms — all inside the researched bands
9 · Formsvalidation moved into the field; 2 placeholder-as-label fixed
10 · Semanticsicon-only controls labelled — both back buttons had none
Bandmakers · UI polish pass · built from the app’s own design tokens. Renders, not photographs.