One of the shortest sentences in my IosShell spec is the one I care about most:
*We say the default palette meets WCAG AA contrast. We make no "508 compliant" or "ADA compliant" claims.*
Why I won't say "compliant"
A color palette can meet a contrast standard. That's a measurable fact about a set of colors.
An app can't be compliant because of its palette. Conformance belongs to the finished product, with its real screens, real content and real behavior, tested against the whole standard. A starter kit can make that outcome far more likely. It can't promise it on behalf of an app that doesn't exist yet.
I spend my days around public-sector accessibility requirements, so I've seen how much weight that word carries. If I put "compliant" in a client's copy, I'd be claiming something I can't know. So the shell says the narrow thing that's true, and leaves certification claims to an audit of the finished app.
What I do commit to
Every screen in the shell has to pass six checks, and each one is pass or fail:
- It works at the largest Dynamic Type size with no clipped text and no unreachable controls.
- It works in light and dark mode, with text pairs meeting 4.5:1 contrast (3:1 for large text and controls).
- Every status carries an icon or a label, not color alone. I'll check by walking every screen in grayscale.
- Every interactive element has a VoiceOver label. An Accessibility Inspector audit has to find none unlabeled.
- Every touch target is at least 44 by 44 points.
- Every error says what happened and what to do next, in plain words: "Couldn't reach the server. Check your connection and try again."
I'm targeting WCAG 2.1 AA, which adds a 3:1 minimum for the edges of controls. The wording rule has a test too: a search of the repository and the client-facing docs has to find no "508 compliant," "ADA compliant," or "certified."
A guardrail, not a guideline
The part I like best is in the branding config. A client will eventually want a lovely pale grey for their secondary text, and a guideline would just ask them not to. The config refuses instead.
VoiceOver When a brand color pair falls under 4.5:1 for text, or 3:1 for large text and controls, the config won't accept it. It names the ratio and suggests the nearest passing shade. The logo can't be saved without alt text. And the status colors for success, warning, and error aren't editable at all.
The default palette ratios come from my brand notes. I recalculated them independently from the hex values before putting them here, because a number I haven't checked is a number I shouldn't publish. They held up. White on the primary blue is 6.7 to 1. The pale grey in the example is 2.5 to 1, and it's blocked.
What this isn't
Honesty requires two caveats.
None of this is built yet. These are the pass conditions I wrote before building, and I haven't run them. I'll tell you when I have and what they find.
And a passing score isn't the same as a good experience. Contrast ratios and label audits catch a lot, but they don't replace putting the app in front of people who use assistive technology every day. That's a gap this spec doesn't cover, and I'd rather name it than hide it.
What's next
Next I'll write about the backend, and how I'm trying to make a points balance impossible to get wrong, even when two requests arrive at the same moment.



