Rams MCP · The full engine, now in your coding agent
t3-oss on GitHub

t3-oss/create-t3-app

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

30 files reviewed·July 9, 2026

Top fix

Add a live region so async loading and greeting text announce changes

See the fix

Verdict

Every reviewer flagged the same five gaps in the same stock scaffold, proving this template gets copy-pasted forward untouched. The real danger isn't the current page, it's every project inheriting its silent loading states and invisible focus hierarchy.

Files Rams reviewed

cli/template/extras/src/app/_components/post-tw.tsx

cli/template/extras/src/app/_components/post.tsx

cli/template/extras/src/app/page/base.tsx

cli/template/extras/src/app/page/with-auth-trpc-tw.tsx

cli/template/extras/src/app/page/with-auth-trpc.tsx

cli/template/extras/src/app/page/with-better-auth-trpc-tw.tsx

cli/template/extras/src/app/page/with-better-auth-trpc.tsx

cli/template/extras/src/app/page/with-better-auth-tw.tsx

cli/template/extras/src/app/page/with-better-auth.tsx

cli/template/extras/src/app/page/with-trpc-tw.tsx

cli/template/extras/src/app/page/with-trpc.tsx

cli/template/extras/src/app/page/with-tw.tsx

cli/template/extras/src/pages/index/base.tsx

cli/template/extras/src/pages/index/with-auth-trpc-tw.tsx

cli/template/extras/src/pages/index/with-auth-trpc.tsx

cli/template/extras/src/pages/index/with-better-auth-trpc-tw.tsx

cli/template/extras/src/pages/index/with-better-auth-trpc.tsx

cli/template/extras/src/pages/index/with-better-auth-tw.tsx

cli/template/extras/src/pages/index/with-better-auth.tsx

cli/template/extras/src/pages/index/with-trpc-tw.tsx

cli/template/extras/src/pages/index/with-trpc.tsx

cli/template/extras/src/pages/index/with-tw.tsx

www/src/components/docs/breadCrumbs.tsx

www/src/components/docs/companyList.tsx

www/src/components/docs/introductionTab.tsx

www/src/components/docs/openSourceAppList.tsx

www/src/components/landingPage/ClipboardSelect.tsx

www/src/components/landingPage/cli.tsx

www/src/components/navigation/LanguageSelect.tsx

www/src/components/navigation/OnThisPageLinks.tsx

96/100

Accessibility

2 serious
Accessibility·cli/template/extras/src/pages/index/with-better-auth-trpc.tsx:44Serious

tRPC loading and greeting text swap silently with no live region

`<p className={styles.showcaseText}>{hello.data ? hello.data.greeting : "Loading tRPC query..."}</p>` changes content once the query resolves, but the paragraph has no `role="status"` or `aria-live`.

Why it matters

Sighted users see the text flip from "Loading tRPC query..." to the greeting, but screen reader users get no announcement that the async fetch finished or what it returned.

Fix

Mark the async status text with aria-live="polite" so assistive tech announces the update.

<p className={styles.showcaseText}>
  {hello.data ? hello.data.greeting : "Loading tRPC query..."}
</p>
<p className={styles.showcaseText} aria-live="polite">
  {hello.data ? hello.data.greeting : "Loading tRPC query..."}
</p>
Accessibility·cli/template/extras/src/pages/index/with-better-auth-tw.tsx:60Serious

Session loading state is invisible to screen reader users

The `isPending` branch renders `<p className="text-2xl text-white">Loading...</p>` with no `role="status"` or `aria-live` attribute.

Why it matters

Sighted users see the loading text appear and disappear; screen reader users get no announcement that the session is resolving or has finished, so they can't tell whether the page is ready.

Fix

Mark async status text with role='status' or aria-live='polite' so assistive tech announces it.

if (isPending) {
  return <p className="text-2xl text-white">Loading...</p>;
}
if (isPending) {
  return (
    <p role="status" className="text-2xl text-white">
      Loading...
    </p>
  );
}
98/100

Typography

1 serious
Typography·cli/template/extras/src/pages/index/with-auth-trpc-tw.tsx:27Serious

Arrow glyphs as link affordances render inconsistently across fonts

Both card headings, "First Steps →" and "Documentation →", use the literal `→` character baked into the string to signal an external link.

Why it matters

The glyph's weight and baseline position come from whatever font is active, so it can render heavy, off-baseline, or missing entirely in some font stacks, undercutting the link affordance it's meant to provide.

Fix

Replace the character with an inline stroke SVG arrow icon that matches the type weight exactly.

<h3 className="text-2xl font-bold">First Steps →</h3>
<h3 className="flex items-center gap-1.5 text-2xl font-bold">First Steps<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="m9 18 6-6-6-6"/></svg></h3>

Want this on your repo?

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

Review my public repo for free
98/100

Color

1 serious
Design System·cli/template/extras/src/pages/index/with-better-auth-trpc-tw.tsx:17Serious

Hero background and accent text hardcode raw hex and HSL values

The `<main>` uses `bg-gradient-to-b from-[#2e026d] to-[#15162c]` and the "T3" span uses `text-[hsl(280,100%,70%)]`, both arbitrary Tailwind bracket values with no token behind them.

Why it matters

Colors defined inline instead of through tokens can't be reused, themed, or updated consistently, and every new page risks introducing a slightly different purple.

Fix

Move these values into the Tailwind config or CSS variables as named tokens (e.g. brand-950, brand-accent) instead of inline arbitrary values.

<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c]">
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-brand-950 to-brand-900">
98/100

UX

1 serious
UX·cli/template/extras/src/pages/index/base.tsx:18Serious

No focal point on the page: heading and two identical cards carry equal weight

The page is `<h1>Create T3 App</h1>` followed by two visually identical `Link` cards ("First Steps →" and "Documentation →") with matching structure, size, and no distinguishing treatment between them.

Why it matters

With no visual hierarchy beyond the title, a new user landing here has no cue about which link to try first, so both compete equally for attention on a page whose entire job is to orient a first-time visitor.

Fix

Give one card a stronger visual treatment (border, accent, or order) to signal the recommended starting point.

<div className={styles.cardRow}>
  <Link
    className={styles.card}
    href="https://create.t3.gg/en/usage/first-steps"
    target="_blank"
  >
<div className={styles.cardRow}>
  <Link
    className={`${styles.card} ${styles.cardPrimary}`}
    href="https://create.t3.gg/en/usage/first-steps"
    target="_blank"
  >
98/100

Craft

1 serious
Design System·cli/template/extras/src/pages/index/with-better-auth-trpc-tw.tsx:20Serious

Hero title jumps to an arbitrary 5rem size on desktop

The `<h1>` uses `sm:text-[5rem]`, an arbitrary bracket value, instead of a scale step like `text-8xl` or `text-9xl`.

Why it matters

Arbitrary sizes accumulate one-off values across a codebase that don't map to any shared scale, making it harder to keep type sizes consistent as more pages get added.

Fix

Use the nearest Tailwind scale step instead of a bracketed arbitrary value.

<h1 className="text-5xl font-extrabold tracking-tight text-white sm:text-[5rem]">
<h1 className="text-5xl font-extrabold tracking-tight text-white sm:text-8xl">

Spacing

No issues found

Components

No issues found

Motion

No issues found

Working well

  • Wrapping the greeting text in a conditional (`hello.data ? hello.data.greeting : "Loading tRPC query..."`) means the layout never collapses to nothing while the query resolves: this is the right instinct even though the error branch is still missing.
  • The sign in/sign out buttons are real `<button type="button">` elements, not clickable divs, so keyboard focus, Enter/Space activation, and screen reader announcement all work for free. Native semantics here save a whole category of a11y bugs.
  • The two auth buttons ("Sign out" and "Sign in with GitHub") never render at the same time since they're mutually exclusive on `sessionData`, so hierarchy stays clear: there's always exactly one primary action visible, never two competing CTAs.
  • The two card links share one structural pattern (heading + description inside a `styles.card` link) instead of two bespoke layouts, which is the right instinct: repeating a proven structure keeps the page predictable even at this small scale.

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.