steven-tey/precedent
Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.
25 files reviewed·July 9, 2026
More findings
Verdict
Polished structure hides a hero that can vanish entirely for reduced-motion users and a badge that fails contrast against its own pill. The credit-where-due note: Clerk wrapping, Suspense boundaries, and lang attributes are all correctly in place, so this is a finishing problem, not an architecture problem.
Files Rams reviewed
app/layout.tsx
app/page.tsx
app/opengraph-image.tsx
components/home/card.tsx
components/home/component-grid.tsx
components/home/demo-modal.tsx
components/home/web-vitals.tsx
components/layout/navbar.tsx
components/shared/counting-numbers.tsx
components/shared/icons/buymeacoffee.tsx
components/shared/icons/expanding-arrow.tsx
components/shared/icons/github.tsx
components/shared/icons/google.tsx
components/shared/icons/loading-circle.tsx
components/shared/icons/loading-spinner.module.css
components/shared/modal.tsx
components/shared/popover.tsx
components/shared/tooltip.tsx
app/globals.css
components/shared/icons/index.tsx
components/layout/footer.tsx
components/shared/icons/loading-dots.module.css
components/shared/icons/loading-dots.tsx
components/shared/icons/loading-spinner.tsx
components/shared/icons/twitter.tsx
Color
"Introducing Precedent" badge text fails contrast against its own pill
The `<Twitter>` icon and the "Introducing Precedent" text both use `text-[#1d9bf0]` on the pill's `bg-blue-100` background.
Why it matters
Blending #1d9bf0 against #dbeafe computes to roughly 2.5:1, well under the 4.5:1 AA floor for text this size (14px). The first thing on the page is nearly unreadable for low-vision users.
Fix
Darken the text color on light backgrounds until the ratio clears 4.5:1.
<Twitter className="h-5 w-5 text-[#1d9bf0]" />
<p className="text-sm font-semibold text-[#1d9bf0]">
Introducing Precedent
</p><Twitter className="h-5 w-5 text-blue-700" />
<p className="text-sm font-semibold text-blue-700">
Introducing Precedent
</p>Background gradient mixes indigo and cyan while heading mixes black and stone
The card runs three unrelated hues in one composition: `#E0E7FF` (indigo), `#CFFAFE` (cyan) on the backdrop, and `#000000` to `#78716c` (stone) on the heading text.
Why it matters
Three disconnected color families in a single 1200x630 card reads as unedited rather than a deliberate brand mark, and it's the first visual impression anyone gets when the link is shared on social platforms.
Fix
Pick one hue family for the backdrop and keep the heading gradient monochrome or on the same hue so the card reads as one composition.
backgroundImage:
"linear-gradient(to bottom right, #E0E7FF 25%, #ffffff 50%, #CFFAFE 75%)",backgroundImage:
"linear-gradient(to bottom right, #EEF2FF 25%, #ffffff 50%, #E0E7FF 75%)",Accessibility
No skip-to-content link forces keyboard users through the nav on every page
The body renders `<Navbar />` then `<main>` directly with no landmark bypass. Keyboard and screen-reader users must tab through every nav item before reaching page content on every single route.
Why it matters
Every keyboard-only visitor pays this tax on every page load, which compounds across a multi-page app and is one of the most cited WCAG 2.4.1 failures in production sites.
Fix
Add a visually-hidden skip link at the top of body that jumps focus to the main landmark.
<body className={cx(sfPro.variable, inter.variable)}><body className={cx(sfPro.variable, inter.variable)}>
<a href="#main-content" className="sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4">Skip to content</a>"Deploy to Vercel" primary CTA has a sub-40px tap target
The "Deploy to Vercel" link uses `px-5 py-2`, giving roughly 8px of vertical padding on each side around a 14px line, for a total control height near 36px.
Why it matters
This is the page's primary conversion action; under ~40px it's harder to hit reliably on mobile and sits below the AAA 44px guidance for primary actions.
Fix
Increase vertical padding on the primary CTA so the hit area reaches at least 44px.
className="group flex max-w-fit items-center justify-center space-x-2 rounded-full border border-black bg-black px-5 py-2 text-sm text-white transition-colors hover:bg-white hover:text-black"className="group flex max-w-fit items-center justify-center space-x-2 rounded-full border border-black bg-black px-5 py-3 text-sm text-white transition-colors hover:bg-white hover:text-black"Want this on your repo?
Rams reviews your next PR automatically and posts inline fix suggestions.
Review my public repo for freeMotion
Hero content stays permanently invisible for reduced-motion users
The badge, "Building blocks for your Next project" heading, subhead, and CTA row all start at `opacity-0` and rely on the `animate-fade-up` keyframe plus `animationFillMode: "forwards"` to reveal themselves. There is no `prefers-reduced-motion` guard anywhere in the file or a `motion-safe:` prefix on these classes.
Why it matters
Users with `prefers-reduced-motion` enabled never trigger the animation, so the elements sit at opacity 0 forever: the entire hero, including the primary CTAs, is invisible to them.
Fix
Gate entrance animations behind motion-safe so reduced-motion users see full-opacity content immediately.
className="animate-fade-up bg-gradient-to-br from-black to-stone-500 bg-clip-text text-center font-display text-4xl font-bold tracking-[-0.02em] text-transparent opacity-0 drop-shadow-sm [text-wrap:balance] md:text-7xl md:leading-[5rem]"className="motion-safe:animate-fade-up bg-gradient-to-br from-black to-stone-500 bg-clip-text text-center font-display text-4xl font-bold tracking-[-0.02em] text-transparent opacity-100 motion-safe:opacity-0 drop-shadow-sm [text-wrap:balance] md:text-7xl md:leading-[5rem]"Typography
Heading drops from bold to normal weight exactly as it gets bigger on desktop
The `<h2>` for {title} is `text-xl font-bold` on mobile but switches to `md:text-3xl md:font-normal` on desktop. Weight and size move in opposite directions across the breakpoint.
Why it matters
The heading is the card's entry point; losing weight right as it gets larger flattens the emphasis instead of reinforcing it, so the title reads less confident on wider screens where it should read stronger.
Fix
Keep heading weight consistent across breakpoints; scale size only.
<h2 className="bg-gradient-to-br from-black to-stone-500 bg-clip-text font-display text-xl font-bold text-transparent [text-wrap:balance] md:text-3xl md:font-normal"><h2 className="bg-gradient-to-br from-black to-stone-500 bg-clip-text font-display text-xl font-bold text-transparent text-balance md:text-3xl">Spacing
Components
UX
Craft
Working well
- "Deploy to Vercel" (solid black fill, white text) and "Star on GitHub" (white fill, gray border and text) are clearly differentiated by weight, not just color: the filled button reads as the committed action, the outlined one as secondary. This is exactly how a two-CTA row should split hierarchy.
- The markdown link override styles `<a>` as `font-medium text-gray-800 underline`, clearly distinct from the surrounding `text-gray-500` body copy. This works because a link needs a visibly different weight and color from prose text so it reads as clickable without relying on hover alone.
- The `large` prop on the feature grid's first `Card` ("Beautiful, reusable components") breaks the monotony of an otherwise uniform 3-column grid by giving the lead feature more visual room, so the eye has a clear entry point into the section instead of six identical tiles.
- Layout classes (`rounded-xl`, `shadow-md`, `mx-auto`, `max-w-lg`) all come from Tailwind's standard scale rather than bracket values, which keeps this card's spacing and radius consistent with the rest of a token-based system.
Score your own repo with Rams.
Free on public repos. Rams reviews every pull request for accessibility, color, type, spacing, components, motion, UX, and craft, and posts inline fixes.