cogapplabs/famsf-wireframes
Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.
30 files reviewed·July 31, 2026
Elevated
Accessibility needs attention.
More findings
Verdict
A disciplined, restrained wireframe system undone by one lazy default: gray-300/400 reused everywhere without checking it against background or size. The arrow-only tracker link is the loudest failure, but the real risk is that the same unchecked gray habit repeats across cards, headings, and placeholders.
Files Rams reviewed
src/app/(wireframes)/accessibility-statement/page.tsx
src/app/(wireframes)/collection-area/[slug]/[featured]/page.tsx
src/app/(wireframes)/constituents/sample/page.tsx
src/app/(wireframes)/curator-deviations/page.tsx
src/app/(wireframes)/feature-status/page.tsx
src/app/(wireframes)/layout.tsx
src/app/(wireframes)/objects/sample/page.tsx
src/app/(wireframes)/prototypes/visual-browse/page.tsx
src/app/(wireframes)/search-results/page.tsx
src/app/(wireframes)/sitemap/page.tsx
src/app/page.tsx
src/app/(wireframes)/artist-search/page.tsx
src/app/(wireframes)/collection-area/page.tsx
src/app/(wireframes)/collector-page/page.tsx
src/app/(wireframes)/educational-resources/page.tsx
src/app/(wireframes)/exhibition-detail/page.tsx
src/app/(wireframes)/exhibitions/page.tsx
src/app/(wireframes)/explore/page.tsx
src/app/(wireframes)/image-orders/page.tsx
src/app/(wireframes)/my-finds/page.tsx
src/app/(wireframes)/parent-record/page.tsx
src/app/(wireframes)/portfolio-detail/page.tsx
src/app/(wireframes)/prototypes/drift/page.tsx
src/app/(wireframes)/seed-journey/page.tsx
src/app/(wireframes)/visit-planner/page.tsx
src/app/layout.tsx
src/app/login/page.tsx
src/app/(wireframes)/artist-search/ArtistSearchClient.tsx
src/app/(wireframes)/collection-area/[slug]/page.tsx
src/app/(wireframes)/collection-landing/page.tsx
Accessibility
src/app/(wireframes)/feature-status/page.tsx:168
Tracker link exposes only an arrow glyph to screen readers
In the feature status table, every row's tracker link renders <ExternalLink href={s.issueUrl} hideIcon>↗</ExternalLink>, so the glyph "↗" is the link's only accessible content. There is no aria-label and no visible text describing the destination.
Why it matters
Screen reader users hear a raw glyph with no context and can't tell the link opens a tracker issue, which locks them out of that row's data entirely.
Fix
Add an aria-label that names the destination so assistive technology announces the link's purpose.
<ExternalLink
href={s.issueUrl}
className="text-gray-500 underline decoration-gray-300 hover:decoration-gray-700"
hideIcon
>
↗
</ExternalLink><ExternalLink
href={s.issueUrl}
className="text-gray-500 underline decoration-gray-300 hover:decoration-gray-700"
aria-label={`Open tracker issue for ${s.label}`}
hideIcon
>
↗
</ExternalLink>src/app/page.tsx:116
Prototypes section heading fails contrast at its label size
The "Prototypes" heading at line 116 uses text-purple-500 at text-label size (~11px). Against the white page background this computes to roughly 3.79:1, which only clears AA for large text, not this small label.
Why it matters
Low-vision users struggle to read the section label that anchors this part of the page, weakening wayfinding on first scan.
Fix
Darken the heading color to a shade that reaches 4.5:1 at this text size.
<h2 className="mb-1 font-mono text-label tracking-[0.08em] text-purple-500"><h2 className="mb-1 font-mono text-label tracking-[0.08em] text-purple-700">src/app/(wireframes)/constituents/sample/page.tsx:27
Recurring gray-400 metadata text fails contrast across sample cards
The sample constituent card repeats text-gray-400 for core metadata: the display_date span (line 27), the tags line (line 40), and the "fields" unit label (line 49), all sitting on a hover:bg-gray-50 card. Each instance measures roughly 2.43:1 against the background.
Why it matters
Date, tags, and field count are the scannable facts this index exists to surface, so low contrast on all three makes comparing records across cards harder for low-vision users.
Fix
Darken this recurring metadata color to a shade that reaches 4.5:1 while keeping it visually secondary to the heading.
<span className="ml-3 font-mono text-label text-gray-400">
{doc.display_date}
</span><span className="ml-3 font-mono text-label text-gray-500">
{doc.display_date}
</span>src/app/(wireframes)/accessibility-statement/page.tsx:109
Contact us link has no visible focus indicator for keyboard users
The "Contact us" mailto link (line 109) is styled as a bordered button with a hover state (hover:border-gray-500) but defines no focus-visible treatment.
Why it matters
This is the page's only interactive control besides navigation; keyboard users tabbing to it get no visible indication of focus, so they can't confirm they've reached the right element before activating it.
Fix
Add a focus-visible outline or ring that matches the existing hover treatment.
className="border border-gray-300 px-3 py-1.5 inline-block hover:border-gray-500"className="border border-gray-300 px-3 py-1.5 inline-block hover:border-gray-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500"src/app/page.tsx:55
MVP only toggle falls short of the 44px touch target minimum
The "MVP only" filter button at line 55 combines px-3 py-1.5 padding with text-label sized content, yielding roughly 28-30px of height.
Why it matters
On touch devices this button sits well under the accepted 44px minimum, so users with limited dexterity or on mobile mis-tap it more often.
Fix
Increase vertical padding or set a minimum height so the control reaches the 44px touch target.
className={`flex items-center gap-2 border px-3 py-1.5 font-mono text-label tracking-[0.08em] transition-colors ${className={`flex min-h-[44px] items-center gap-2 border px-3 py-2.5 font-mono text-label tracking-[0.08em] transition-colors ${Color
src/app/(wireframes)/feature-status/page.tsx:159
Empty note and tracker placeholder is nearly invisible
When a section has no note or no tracker link, the table renders <span className="text-gray-300">: </span> at lines 159 and 171. text-gray-300 on white measures roughly 1.4:1.
Why it matters
Users scanning the table can't tell whether a cell is intentionally empty or failed to load, since the placeholder is nearly invisible against the white background.
Fix
Darken the placeholder dash to a shade that stays visually muted but reads clearly.
{s.note ?? <span className="text-gray-300">–</span>}{s.note ?? <span className="text-gray-400">–</span>}Typography
Spacing
Components
Motion
UX
Craft
Working well
- The 'MVP only' toggle pairs a filled emerald state (border-emerald-400, bg-emerald-50, text-emerald-700) against a neutral ghost state rather than relying on color alone, so the on/off condition reads clearly even without color perception.
- The known-gaps section on the accessibility statement pairs each limitation with plain descriptive text instead of omitting it, which is honest disclosure rather than marketing gloss.
- MvpBadge and PostMvpBadge use shape, border, and a text label together rather than color alone, so status is legible for colorblind users scanning the feature status table.
Scored July 31, 2026 with Rams Engine v0.0.3 · Engine changelog
This page is an automated design review of cogapplabs/famsf-wireframes’s UI code: 30 files read against 291 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; any confirmed critical issue caps it at 59.
More design scores
Score your own repo.
Free on public repos, no account. The same engine that scored this page reads your UI code and mints a score page like this one.
Public repos only. The full engine reviews the UI code and mints a public score page — we email you the link too. Already-scored repos open instantly.