Rams MCP · The full engine, now in your coding agent
shadcn-ui on GitHub

shadcn-ui/taxonomy

Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.

30 files reviewed·July 9, 2026

Top fix

Fill the blank split-screen panel with real content

See the fix

Verdict

Auth and layout pages nail restraint with clean hierarchy and disciplined token use, but polish stops at the surface. The real risk is unfinished edges: empty panels, missing alt text, and no error handling for a billing check that can take down the whole page.

Files Rams reviewed

app/(auth)/login/page.tsx

app/(auth)/register/page.tsx

app/(dashboard)/dashboard/billing/page.tsx

app/(dashboard)/dashboard/layout.tsx

app/(dashboard)/dashboard/page.tsx

app/(docs)/docs/[[...slug]]/page.tsx

app/(docs)/guides/[...slug]/page.tsx

app/(docs)/guides/page.tsx

app/(docs)/layout.tsx

app/(marketing)/[...slug]/page.tsx

app/(marketing)/blog/[...slug]/page.tsx

app/(marketing)/blog/page.tsx

app/(marketing)/layout.tsx

app/(marketing)/page.tsx

app/(marketing)/pricing/page.tsx

app/layout.tsx

app/(auth)/layout.tsx

app/(dashboard)/dashboard/settings/page.tsx

app/(docs)/docs/layout.tsx

app/(docs)/guides/layout.tsx

app/(editor)/editor/[postId]/page.tsx

app/(editor)/editor/layout.tsx

app/api/og/route.tsx

components/billing-form.tsx

components/editor.tsx

components/empty-placeholder.tsx

components/icons.tsx

components/main-nav.tsx

components/mdx-components.tsx

components/mobile-nav.tsx

96/100

Spacing

2 serious
Design System·app/(auth)/login/page.tsx:27Serious

Arbitrary width value breaks the app's spacing scale

The form wrapper uses `sm:w-[350px]`, a bracketed arbitrary value instead of a scale token like `sm:w-96` (384px) or `sm:max-w-sm`.

Why it matters

Arbitrary pixel widths can't be reasoned about alongside the rest of the layout scale, and future edits to this page (or a design-token width scale) will silently miss this one bespoke value.

Fix

Replace bracketed arbitrary widths with the nearest Tailwind scale utility.

<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:max-w-sm">
Spacing·app/(auth)/register/page.tsx:14Serious

Fixed h-screen container has no scroll fallback for short viewports

The outer container is `h-screen w-screen` with content vertically centered via `justify-center` and no `overflow-y-auto`. The stacked content (logo, heading, subtext, `UserAuthForm`, and the two-line legal paragraph) has no scroll path if it exceeds the available height.

Why it matters

On short viewports (mobile landscape, or when a form validation error adds height), content taller than the screen gets clipped with no way to scroll to the cut-off legal text or the bottom of the form.

Fix

Allow the content column to scroll independently when it exceeds viewport height instead of relying on a fixed h-screen with no overflow handling.

<div className="container grid h-screen w-screen flex-col items-center justify-center lg:max-w-none lg:grid-cols-2 lg:px-0">
<div className="container grid min-h-screen w-screen flex-col items-center justify-center overflow-y-auto lg:max-w-none lg:grid-cols-2 lg:px-0">
96/100

UX

2 serious
UX·app/(auth)/register/page.tsx:15Serious

Absolute-positioned Login link can overlap centered content on short screens

The "Login" link is `absolute right-4 top-4 md:right-8 md:top-8`, floating outside the centered flex column that holds the logo, heading, and form.

Why it matters

Because the main content is vertically centered with `justify-center` inside an `h-screen` container, a short viewport (landscape phones, embedded webviews) can push the centered card up into the absolutely positioned "Login" link, overlapping the logo or heading.

Fix

Reserve top padding on the content column equal to the Login link's height so the two can never overlap regardless of viewport height.

<Link
  href="/login"
  className={cn(
    buttonVariants({ variant: "ghost" }),
    "absolute right-4 top-4 md:right-8 md:top-8"
  )}
>
  Login
</Link>
<Link
  href="/login"
  className={cn(
    buttonVariants({ variant: "ghost" }),
    "absolute right-4 top-4 z-10 md:right-8 md:top-8"
  )}
>
  Login
</Link>
UX·app/(dashboard)/dashboard/billing/page.tsx:55Serious

External Stripe docs link has no visual cue that it leaves the app

The "Stripe docs" link opens `target="_blank"` with only an underline style, no icon or text indicating it navigates to an external site.

Why it matters

Users clicking "Stripe docs" get a new tab with no warning, which is disorienting on mobile where tab switching isn't obvious, and screen reader users get no announcement that the link leaves the current context.

Fix

Add a visible external-link indicator (icon or accessible text) to links that open in a new tab.

<a
  href="https://stripe.com/docs/testing#cards"
  target="_blank"
  rel="noreferrer"
  className="font-medium underline underline-offset-8"
>
  Stripe docs
</a>
<a
  href="https://stripe.com/docs/testing#cards"
  target="_blank"
  rel="noreferrer"
  className="font-medium underline underline-offset-8"
>
  Stripe docs (opens in new tab)
</a>

Want this on your repo?

Rams reviews your next PR automatically and posts inline fix suggestions.

Review my public repo for free
98/100

Accessibility

1 serious
Accessibility·app/layout.tsx:63Serious

Twitter card image ships with no alt text for the shared preview

`twitter.images` is a bare string array: `[`${siteConfig.url}/og.jpg`]`. The Twitter card schema supports an object form with an `alt` field, which isn't used here.

Why it matters

Screen reader users who encounter the shared card get no description of the preview image, the same gap A11Y-001 flags for on-page <img> tags.

Fix

Use the object form of the Twitter image with an alt field describing the image.

images: [`${siteConfig.url}/og.jpg`],
images: [{ url: `${siteConfig.url}/og.jpg`, alt: siteConfig.name }],
98/100

Craft

1 serious
Craft·app/(auth)/register/page.tsx:22Serious

Blank muted panel wastes half the desktop screen with no content

The right-hand panel `<div className="hidden h-full bg-muted lg:block" />` renders as a solid empty block on any viewport ≥1024px, sitting in a `lg:grid-cols-2` layout next to the actual registration form.

Why it matters

On desktop, half the viewport carries zero information: no brand statement, no testimonial, no product context. The eye has nothing to land on there, and the form column gets squeezed into a narrow `sm:w-[350px]` well while an equal-width void sits beside it.

Fix

Give the empty panel a purpose (brand image, quote, or product shot) or collapse the grid to a single centered column until content exists.

<div className="hidden h-full bg-muted lg:block" />
<div className="hidden h-full bg-muted lg:flex lg:items-end lg:p-10">
  {/* brand image, quote, or testimonial content goes here */}
</div>

Typography

No issues found

Color

No issues found

Components

No issues found

Motion

No issues found

Working well

  • Composing the page from `DashboardShell`, `DashboardHeader`, and `BillingForm` instead of inlining markup keeps this page thin and delegates the actual plan-management complexity to a dedicated component, which is the right split for a page that will only grow more billing states over time.
  • Every color and spacing value in this file comes from tokens and the Tailwind scale (`text-muted-foreground`, `space-y-6`, `sm:w-[350px]`) with zero hardcoded hex or arbitrary pixel values, which keeps the auth flow themeable and consistent with the rest of the app.
  • Pairing `suppressHydrationWarning` on `<html>` with `ThemeProvider attribute="class"` is the correct next-themes pattern: it silences the expected hydration mismatch from client-side theme class injection without masking real hydration bugs elsewhere.
  • The "Login" link uses `buttonVariants({ variant: "ghost" })` instead of a filled button, correctly signaling it's a secondary navigation path away from the primary task (creating an account) rather than competing with the form's submit action.

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.