usememos on GitHub

usememos/memos

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.

5issues
Serious & Moderate · top 4 shown below

Top fix

Replace arbitrary bracket values with tokens from the type and spacing scale

See the fix

Verdict

Solid structural patterns get undermined by scale drift and a confirm dialog that won't say what it's deleting. The state machine in Attachments.tsx shows real design discipline, but arbitrary bracket values and a faded label are chipping away at it.

Files Rams reviewed

web/src/components/AuthPageLayout.tsx

web/src/components/ConfirmDialog/index.tsx

web/src/components/MemoContent/index.tsx

web/src/components/MemoEditor/Editor/index.tsx

web/src/components/MemoEditor/index.tsx

web/src/components/Placeholder/index.tsx

web/src/pages/About.tsx

web/src/pages/AdminSignIn.tsx

web/src/pages/Archived.tsx

web/src/pages/Attachments.tsx

web/src/pages/AuthCallback.tsx

web/src/pages/Explore.tsx

web/src/pages/Home.tsx

web/src/pages/Inboxes.tsx

web/src/pages/MemoDetail.tsx

web/src/pages/Setting.tsx

web/src/pages/SignIn.tsx

web/src/pages/SignUp.tsx

web/src/pages/UserProfile.tsx

web/src/components/ActivityCalendar/CalendarCell.tsx

web/src/components/ActivityCalendar/MonthCalendar.tsx

web/src/components/ActivityCalendar/YearCalendar.tsx

web/src/components/AttachmentIcon.tsx

web/src/components/AttachmentLibrary/AttachmentFileRows.tsx

web/src/components/AttachmentLibrary/AttachmentLibraryEmptyState.tsx

web/src/components/AttachmentLibrary/AttachmentLibraryPrimitives.tsx

web/src/components/AttachmentLibrary/AttachmentLibraryStates.tsx

web/src/components/AttachmentLibrary/AttachmentLibraryToolbar.tsx

web/src/components/AttachmentLibrary/AttachmentMediaGrid.tsx

web/src/components/AuthFooter.tsx

98/100

Accessibility

1 serious
AccessibilitySerious

web/src/pages/About.tsx:30

Section labels shrink to 11px at 55% opacity, risking illegibility

The shared SectionLabel component renders "Build" and "Project" at 11px with text-muted-foreground/55, well under the 12px legibility floor and stacking a low-contrast token on top of a reduced size.

Why it matters

Combining sub-12px type with a heavily faded muted-foreground token likely pushes contrast below 4.5:1, so users skimming the About page for section boundaries strain to read the labels, and low-vision users may miss them entirely.

Fix

Raise the label to at least 12px and use a solid or higher-opacity muted-foreground value so contrast clears 4.5:1 for small text.

const SectionLabel = ({ children }: { children: React.ReactNode }) => (
  <h2 className="text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground/55">{children}</h2>
);
const SectionLabel = ({ children }: { children: React.ReactNode }) => (
  <h2 className="text-xs font-medium uppercase tracking-[0.08em] text-muted-foreground">{children}</h2>
);
98/100

Typography

1 serious
TypographySerious

web/src/pages/About.tsx:88

Six arbitrary bracket values bypass the type and spacing scale

The tagline paragraph uses text-[26px] and tracking-[-0.015em], the build rows use grid-cols-[110px_1fr] and text-[13px], repeating one-off pixel values instead of scale utilities like text-2xl or a defined grid-cols token.

Why it matters

Each bespoke value is a magic number nobody else can reuse, so the next section built on this page invents its own 13px or 26px instead of reaching for a shared step, and the type scale drifts further from the rest of the app.

Fix

Replace arbitrary bracket utilities with the closest defined step in the type/spacing scale, or add the value to the scale if it's genuinely needed twice.

<p className="mt-1 max-w-md text-[26px] font-light leading-snug tracking-[-0.015em] text-foreground">{instanceTagline}</p>
...
<div key={row.label} className="grid grid-cols-[110px_1fr] items-center border-b border-border/60 py-2">
  <dt className="text-[13px] text-muted-foreground">{row.label}</dt>
<p className="mt-1 max-w-md text-2xl font-light leading-snug tracking-tight text-foreground">{instanceTagline}</p>
...
<div key={row.label} className="grid grid-cols-[7rem_1fr] items-center border-b border-border/60 py-2">
  <dt className="text-sm text-muted-foreground">{row.label}</dt>

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 free
98/100

Spacing

1 serious
SpacingSerious

web/src/pages/Attachments.tsx:175

Content wrapper uses arbitrary min-h-[16rem] instead of the scale

The results wrapper around renderContent() sets min-h-[16rem] instead of the equivalent scale utility min-h-64.

Why it matters

A hand-picked rem value outside the spacing scale means this page's minimum content height can't be reasoned about alongside every other min-h usage in the app, so spacing drifts file by file as more one-offs accumulate.

Fix

Use the standard scale utility that maps to the same value so spacing stays tied to the token system.

<div className="min-h-[16rem] pt-1">
<div className="min-h-64 pt-1">
98/100

UX

1 serious
UXSerious

web/src/pages/Attachments.tsx:205

Bulk-delete confirmation dialog doesn't name what's being deleted

The ConfirmDialog for clearing unused attachments sets confirmLabel={t("common.delete")}, a generic "Delete" button on a destructive, irreversible bulk action that removes every unused attachment at once.

Why it matters

A generic confirm label reads the same on every destructive dialog in the app, so users can't tell from the button alone that this action wipes an entire batch of files, raising the odds of an accidental confirm on a bulk operation that can't be undone.

Fix

Give the confirm button an action-specific label that names the scope of the delete, not a reused generic string.

confirmLabel={t("common.delete")}
        cancelLabel={t("common.cancel")}
confirmLabel={t("attachment-library.unused.confirm-delete")}
        cancelLabel={t("common.cancel")}

Color

No issues found

Components

No issues found

Motion

No issues found

Craft

No issues found

Working well

  • Attachments.tsx cleanly separates loading, error, empty, and per-tab states inside renderContent, giving every reachable state of the library a designed render instead of leaving gaps for undefined UI.
  • The build and project sections in About.tsx share the same dt/dd grid and border-b/60 rhythm, so two visually different lists read as one consistent system rather than ad hoc formatting.

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

This page is an automated design review of usememos/memos’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