vercel on GitHub

vercel/ai-chatbot

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

30 files reviewed·July 25, 2026

View on GitHub

Elevated

Design risk in this codebase.

2issues
Critical

Top fix

Restore visible focus outlines on all interactive elements

See the fix

Verdict

Polished typography and clean component structure sit on top of an accessibility foundation that's actively hostile to keyboard and low-vision users. The biggest risk is that both critical issues are global defaults, meaning every single page inherits the exclusion.

Files Rams reviewed

app/(auth)/layout.tsx

app/(auth)/login/page.tsx

app/(auth)/register/page.tsx

app/(chat)/layout.tsx

app/layout.tsx

app/(chat)/chat/[id]/page.tsx

app/(chat)/page.tsx

app/globals.css

components/ai-elements/code-block.tsx

components/ai-elements/conversation.tsx

components/ai-elements/message.tsx

components/ai-elements/model-selector.tsx

components/ai-elements/reasoning.tsx

components/ai-elements/shimmer.tsx

components/ai-elements/suggestion.tsx

components/ai-elements/tool.tsx

components/chat/app-sidebar.tsx

components/chat/artifact-actions.tsx

components/chat/artifact-messages.tsx

components/chat/artifact.tsx

components/chat/auth-form.tsx

components/chat/chat-header.tsx

components/chat/code-editor.tsx

components/chat/console.tsx

components/chat/create-artifact.tsx

components/chat/data-stream-handler.tsx

components/chat/data-stream-provider.tsx

components/chat/diffview.tsx

components/chat/document-preview.tsx

components/chat/document-skeleton.tsx

94/100

Accessibility

2 critical
AccessibilityCritical

app/layout.tsx:1

Focus outline removed on every interactive element with no replacement

globals.css strips outline: none on :focus-visible for button, select, [role="button"], input, and textarea with no accompanying box-shadow or ring style defined in the same rule. This affects every button and form control rendered through the app, including the chat input and auth forms.

Why it matters

Keyboard users tabbing through the interface lose all visual indication of which control is focused, making navigation without a mouse effectively unusable.

Fix

Never remove focus-visible outline without substituting a visible focus ring at equal or better contrast.

button:focus-visible,
select:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: none;
}
button:focus-visible,
select:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}
AccessibilityCritical

app/layout.tsx:16

Viewport export locks pinch-zoom, locking out low-vision users

The viewport export in app/layout.tsx sets maximumScale: 1 with no userScalable option. On browsers that honor the meta viewport spec this disables pinch-to-zoom across the entire app, including the chat interface and auth pages.

Why it matters

Low-vision users who rely on pinch-zoom to read chat text or form labels lose that capability app-wide, which is a hard lockout rather than a minor inconvenience.

Fix

Remove maximumScale (or set it to 5 and leave userScalable enabled) so pinch-zoom stays available.

export const viewport = {
  maximumScale: 1,
};
export const viewport = {
  maximumScale: 5,
  userScalable: true,
};

Typography

No issues found

Color

No issues found

Spacing

No issues found

Components

No issues found

Motion

No issues found

UX

No issues found

Craft

No issues found

Working well

  • The 'Sign up' link is styled as a real inline link (underline-offset, hover:underline) rather than a button-shaped anchor, correctly signaling a navigational action distinct from the primary CTA.
  • The back link pairs a small icon with text at consistent gap-1.5 spacing and a subtle hover color shift, which is exactly the right amount of affordance for a secondary navigation action.
  • The layout defers session and cookie reads into an async SidebarShell component gated behind Suspense, keeping the top-level Layout free of blocking data fetches.
  • Using next/font with display: swap for Geist and Geist Mono avoids invisible text during font load, which keeps first paint readable instead of blank.

Scored July 25, 2026 with Rams Engine v0.0.3 · Engine changelog
First scored July 9, 2026: 59/100. This rescore on v0.0.3: 59/100.

This page is an automated design review of vercel/ai-chatbot’s UI code: 30 files read against 309 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; confirmed criticals cap it — one at 59, two at 49, three or more at 39.

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.

Or get a design review on every pull requestInstall Rams