hatchet-dev/hatchet
Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.
30 files reviewed·July 25, 2026
Elevated
Design risk in this codebase.
More findings
Verdict
Solid form scaffolding undercut by sloppy edge details: an unlabeled SSO field, silent validation errors, and a broken back button that never applies its own class. The any-typed toggle setter is the most telling flaw, a compiler-hidden bug sitting quietly in a flow that otherwise looks careful.
Files Rams reviewed
frontend/app/src/pages/auth/components/auth-layout.tsx
frontend/app/src/pages/auth/components/auth-page.tsx
frontend/app/src/pages/error/components/layout.tsx
frontend/app/src/pages/auth/components/social-auth.tsx
frontend/app/src/pages/auth/login/components/user-login-form.tsx
frontend/app/src/pages/auth/register/components/user-register-form.tsx
frontend/app/src/pages/error/components/generic-error.tsx
frontend/app/src/pages/error/components/new-version-available.tsx
frontend/app/src/pages/error/components/not-found.tsx
frontend/app/src/pages/error/components/resource-not-found.tsx
frontend/app/src/pages/error/components/tenant-forbidden.tsx
frontend/app/src/pages/main/info/components/version-info.tsx
frontend/app/src/pages/main/v1/events/components/additional-metadata.tsx
frontend/app/src/pages/main/v1/events/components/event-columns.tsx
frontend/app/src/pages/main/v1/filters/components/filter-columns.tsx
frontend/app/src/pages/main/v1/filters/components/filter-create-form.tsx
frontend/app/src/pages/main/v1/filters/components/filter-detail-view.tsx
frontend/app/src/pages/main/v1/logs/components/logs-chart.tsx
frontend/app/src/pages/main/v1/managed-workers/$managed-worker/components/github-button.tsx
frontend/app/src/pages/main/v1/managed-workers/$managed-worker/components/managed-worker-activity.tsx
frontend/app/src/pages/main/v1/managed-workers/$managed-worker/components/managed-worker-build-logs.tsx
frontend/app/src/pages/main/v1/managed-workers/$managed-worker/components/managed-worker-build.tsx
frontend/app/src/pages/main/v1/managed-workers/$managed-worker/components/managed-worker-iac-logs.tsx
frontend/app/src/pages/main/v1/managed-workers/$managed-worker/components/managed-worker-instances-table.tsx
frontend/app/src/pages/main/v1/managed-workers/$managed-worker/components/managed-worker-logs.tsx
frontend/app/src/pages/main/v1/managed-workers/$managed-worker/components/managed-worker-metrics.tsx
frontend/app/src/pages/main/v1/managed-workers/components/billing-required.tsx
frontend/app/src/pages/main/v1/managed-workers/components/managed-workers-gate.tsx
frontend/app/src/pages/main/v1/managed-workers/components/managed-workers-table.tsx
frontend/app/src/pages/main/v1/managed-workers/components/monthly-usage-card.tsx
Accessibility
frontend/app/src/pages/auth/components/social-auth.tsx:79
SSO email field has no accessible name, only a placeholder
In social-auth.tsx, when the SSO panel expands, the email `<input placeholder="Enter your email">` at line 79 has no `<label>`, `aria-label`, or `aria-labelledby`. Placeholder text disappears once the user starts typing and is never exposed as an accessible name to assistive tech, so a screen reader announces this field as unlabeled.
Why it matters
Screen reader users landing on this input hear only 'edit text' with no indication it wants an email address, so they either skip it or have to guess, blocking SSO sign-in for that group entirely.
Fix
Give every text input a programmatic label via aria-label or a visually-associated <label> element.
<input
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
className="h-10 flex-1 rounded-md border border-muted-foreground/20 bg-background px-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
/><input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
aria-label="Email address"
className="h-10 flex-1 rounded-md border border-muted-foreground/20 bg-background px-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
/>frontend/app/src/pages/auth/register/components/user-register-form.tsx:78
Name field uses an invalid input type that silently falls back to text
The name `<Input>` in user-register-form.tsx (line 74-82) sets `type="name"`, which is not a valid HTML input type. Browsers silently treat it as `type="text"`, so it looks intentional in the code but carries none of the semantics the author likely meant.
Why it matters
Because the type silently degrades instead of erroring, this can sit unnoticed indefinitely; the field just behaves like a generic text box with no functional harm today, but it signals a broader pattern of untyped attributes slipping past review.
Fix
Use a valid HTML input type; plain text fields should be explicit type=text.
type="name"type="text"Color
frontend/app/src/pages/auth/register/components/user-register-form.tsx:82
Error text color fails AA contrast for small text
The validation messages in user-register-form.tsx use `text-sm text-red-500` (line 82 and its two siblings). Tailwind's red-500 (#ef4444) against a white card background computes to roughly 3.8:1, below the 4.5:1 threshold WCAG AA requires for text at this size.
Why it matters
Users with low vision or in bright-light conditions strain to read exactly the messages that tell them their signup failed, at the worst possible moment: right after a rejected submission.
Fix
Raise error text to a darker red shade that clears 4.5:1 contrast against the background, staying within the existing red hue.
className="text-sm text-red-500"className="text-sm text-red-600"Get this score on every PR.
Rams reviews each pull request on your repo and posts inline one-click fixes — about a minute per review.
Install Rams freeComponents
frontend/app/src/pages/auth/components/social-auth.tsx:118
Back button's left-align class is invalid and never applies
The "Back" button in the SSO panel (line 118) uses `className="h-11 justify-left gap-1 ..."`. Tailwind has no `justify-left` utility, only `justify-start`, so this class does nothing and the button falls back to its default flex alignment.
Why it matters
The arrow icon and "Back" text render centered instead of left-aligned as intended, so the button's internal layout is inconsistent with the rest of the panel and doesn't match what the author clearly meant to ship.
Fix
Use the valid Tailwind utility justify-start for left-aligned flex content.
className="h-11 justify-left gap-1 border-muted-foreground/20 bg-background shadow-sm hover:bg-muted/40"className="h-11 justify-start gap-1 border-muted-foreground/20 bg-background shadow-sm hover:bg-muted/40"UX
frontend/app/src/pages/auth/login/components/user-login-form.tsx:78
Login password field has no autocomplete, so password managers can't fill it
In user-login-form.tsx, the password `<Input>` (line 71-77) has `type="password"` but no `autoComplete` attribute, while the email input right above it correctly sets `autoComplete="email"`.
Why it matters
Password managers rely on autoComplete='current-password' to know where to insert a saved credential; without it, users on this sign-in form may have to manually copy their password instead of one-click autofill.
Fix
Add autoComplete=current-password to password inputs on login forms.
<Input
{...register('password')}
id="password"
placeholder="Password"
type="password"
disabled={props.isLoading}
/><Input
{...register('password')}
id="password"
placeholder="Password"
type="password"
autoComplete="current-password"
disabled={props.isLoading}
/>Craft
frontend/app/src/pages/auth/components/social-auth.tsx:52
SSO toggle setter typed as any hides a broken update path from the compiler
`SocialAuthButton` accepts `setSsoExpanded: any` (line 52) instead of `Dispatch<SetStateAction<boolean>>`. It's called with `setSsoExpanded(true)` and `setSsoExpanded(false)` to control the entire SSO expand/collapse panel.
Why it matters
With `any`, a future refactor that changes the setter's shape or passes the wrong value type won't fail the build, so the SSO panel can silently stop opening or closing with no compiler warning to catch it.
Fix
Type state setters with React's Dispatch<SetStateAction<T>> instead of any.
setSsoExpanded: any;setSsoExpanded: Dispatch<SetStateAction<boolean>>;Typography
Spacing
Motion
Working well
- Hiding the decorative gradient panel on mobile with hidden lg:flex and letting the form column go full-width below the breakpoint is the right call: ambient visuals that add nothing functional shouldn't cost layout space or bandwidth on small screens.
- Both the login and register forms pair every input with a real <Label htmlFor> tied to a matching id ("email", "password", "name"), so the core field labeling is correctly accessible even where placeholder text is also present.
- The SSO Continue link correctly disables itself when the email field is empty, using tabIndex={-1}, href="#", and preventDefault together rather than just a visual disabled state, so keyboard users can't tab into a dead link.
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 hatchet-dev/hatchet’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.