Rams MCP · The full engine, now in your coding agent
keephq on GitHub

keephq/keep

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

30 files reviewed·July 25, 2026

View on GitHub

Low

Design risk in this codebase.

4issues
Serious & Moderate · top 3 shown below

Top fix

Add distinct loading, empty, and error states to execution pages

See the fix

Verdict

A tidy, well-plumbed UI that goes completely silent the moment anything deviates from the happy path. The biggest risk is that users can't tell loading from failure from an empty state, all look identical: blank.

Files Rams reviewed

keep-ui/app/(keep)/providers/components/providers-categories/providers-categories.tsx

keep-ui/app/(keep)/dashboard/GridLayout.tsx

keep-ui/app/(keep)/extraction/[rule_id]/executions/[execution_id]/page.tsx

keep-ui/app/(keep)/extraction/[rule_id]/executions/page.tsx

keep-ui/app/(keep)/incidents/[id]/topology/page.tsx

keep-ui/app/(keep)/layout.tsx

keep-ui/app/(keep)/mapping/[rule_id]/executions/[execution_id]/page.tsx

keep-ui/app/(keep)/mapping/[rule_id]/executions/page.tsx

keep-ui/app/(keep)/providers/layout.tsx

keep-ui/app/(keep)/providers/oauth2/[providerType]/page.tsx

keep-ui/app/(keep)/topology/page.tsx

keep-ui/app/(keep)/workflows/[workflow_id]/workflow-detail-page.tsx

keep-ui/app/(keep)/workflows/preview/[workflowId]/page.tsx

keep-ui/app/(keep)/workflows/preview/page.tsx

keep-ui/app/(signin)/layout.tsx

keep-ui/app/(signin)/mobile/page.tsx

keep-ui/app/(keep)/providers/components/providers-filter-by-label/providers-filter-by-label.tsx

keep-ui/app/(keep)/providers/components/providers-search/providers-search.tsx

keep-ui/app/(keep)/[...not-found]/page.tsx

keep-ui/app/(keep)/ai/page.tsx

keep-ui/app/(keep)/alerts/[id]/page.tsx

keep-ui/app/(keep)/alerts/fingerprint/[fp]/page.tsx

keep-ui/app/(keep)/alerts/fingerprint/[fp]/ui/alert-fingerprint-page.tsx

keep-ui/app/(keep)/dashboard/[id]/page.tsx

keep-ui/app/(keep)/deduplication/page.tsx

keep-ui/app/(keep)/extraction/layout.tsx

keep-ui/app/(keep)/extraction/page.tsx

keep-ui/app/(keep)/incidents/[id]/activity/page.tsx

keep-ui/app/(keep)/incidents/[id]/alerts/page.tsx

keep-ui/app/(keep)/incidents/[id]/layout.tsx

96/100

UX

2 serious
UXSerious

keep-ui/app/(keep)/extraction/[rule_id]/executions/[execution_id]/page.tsx:27

Execution details page goes fully blank while loading or on failure

ExtractionExecutionDetailsPage returns `null` whenever `isLoading` is true or `execution` is falsy. That single guard covers three different situations: the initial fetch, a slow network, and a fetch that failed or returned nothing. All three render as an empty white page with no skeleton, spinner, or error message, and no retry action.

Why it matters

A user who lands here after clicking into an execution has no way to tell if the page is still loading, broken, or if the execution simply doesn't exist. They're left guessing whether to wait or navigate away, and a genuine fetch failure gives them no path to recover without a manual refresh.

Fix

Split the loading, error, and not-found states so each renders explicit feedback: a skeleton while loading, an error message with retry on failure, and a distinct empty state when the execution is missing.

if (isLoading || !execution) {
  return null;
}
if (isLoading) {
  return <div className="p-4"><Card><Subtitle>Loading execution…</Subtitle></Card></div>;
}

if (!execution) {
  return (
    <div className="p-4">
      <Card>
        <Title>Execution not found</Title>
        <Subtitle>This execution could not be loaded. It may have been removed or the request failed.</Subtitle>
      </Card>
    </div>
  );
}
UXSerious

keep-ui/app/(keep)/extraction/[rule_id]/executions/page.tsx:34

Executions list page shows nothing while loading or when the rule is missing

ExtractionExecutionsPage returns `null` when `isLoading` is true or `rule` is undefined. As with the detail page, loading and 'rule not found' collapse into the same blank-screen result.

Why it matters

A user navigating to a rule's executions list with a stale or invalid rule_id sees an empty page with no indication of whether it's still loading or whether the rule doesn't exist, so they can't tell whether to wait or go back.

Fix

Separate the loading and not-found branches so each state renders explicit feedback instead of a blank screen.

if (isLoading || !rule) {
  return null;
}
if (isLoading) {
  return <div className="p-4"><Card><Subtitle>Loading executions…</Subtitle></Card></div>;
}

if (!rule) {
  return (
    <div className="p-4">
      <Card>
        <Title>Rule not found</Title>
        <Subtitle>This extraction rule could not be found.</Subtitle>
      </Card>
    </div>
  );
}
98/100

Typography

1 serious
TypographySerious

keep-ui/app/(keep)/extraction/[rule_id]/executions/[execution_id]/page.tsx:89

Extracted field values can overflow the sidebar card with no wrapping

Each entry in 'Extracted Fields' renders `{JSON.stringify(value)}` inside `<div className="mt-1 text-sm">` with no `break-words` or `overflow-wrap` handling. A long string, array, or nested object value serializes to one unbroken token.

Why it matters

Real extraction data (URLs, tokens, nested JSON) commonly exceeds the sidebar's width. Without word-breaking, that value pushes the card wider than its grid column or gets clipped, making the extracted field unreadable next to the logs panel.

Fix

Add break-words (or whitespace-pre-wrap for multi-line JSON) to any container rendering unbounded stringified data so long values wrap instead of overflowing.

<div className="mt-1 text-sm">{JSON.stringify(value)}</div>
<div className="mt-1 text-sm break-words">{JSON.stringify(value)}</div>

Accessibility

No issues found

Color

No issues found

Spacing

No issues found

Components

No issues found

Motion

No issues found

Craft

No issues found

Working well

  • Pagination state is lifted into a typed `Pagination` interface and handed straight to `ExecutionsTable`, keeping the page component thin and the pagination logic contained in one place.
  • The Alert ID link and the 'Extracted Fields' badges both use the same orange accent, keeping a single consistent color meaning across the sidebar instead of scattering unrelated hues.

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

This page is an automated design review of keephq/keep’s UI code: 30 files read against 291 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