Communitygithub.com

ckmirafss/easy-on-the-eyes

Makes websites and web apps comfortable to look at and keeps them from looking generic or AI-generated. Applies and audits evidence-graded rules for text size, contrast, light and dark themes, motion, flashing, stripe patterns and layout stability, and studies real reference sites in a browser to extract their fonts, palette, layout and motion before designing. Use when building or styling UI, setting up color tokens, typography or dark mode, when a page is hard to read, too bright, harsh, tiring, "hurts my eyes" or should be "easy on the eyes", when a design looks templated, generic or like "AI slop", or when the user wants design inspiration from real sites. Handles "/easy-on-the-eyes audit", "fix" and "study <url>". Not for full WCAG compliance audits or personal eye-health advice.

What is easy-on-the-eyes?

easy-on-the-eyes is a Claude Code agent skill that makes websites and web apps comfortable to look at and keeps them from looking generic or AI-generated. Applies and audits evidence-graded rules for text size, contrast, light and dark themes, motion, flashing, stripe patterns and layout stability, and studies real reference sites in a browser to extract their fonts, palette, layout and motion before designing. Use when building or styling UI, setting up color tokens, typography or dark mode, when a page is hard to read, too bright, harsh, tiring, "hurts my eyes" or should be "easy on the eyes", when a design looks templated, generic or like "AI slop", or when the user wants design inspiration from real sites. Handles "/easy-on-the-eyes audit", "fix" and "study <url>". Not for full WCAG compliance audits or personal eye-health advice.

Works with~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ckmirafss/easy-on-the-eyes/tree/HEAD/skills/easy-on-the-eyes

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Easy on the Eyes

Most eye strain at a screen comes from things a website cannot touch: blinking, focus distance, uncorrected vision, the room. What a site controls is how much extra visual work it asks for. This skill removes that extra work and says how strong the evidence is for each rule.

It also keeps a comfortable page from looking like a template. It studies real, shipped sites before designing, and it carries a set of craft rules for the choices that make work look generated.

The claim you are allowed to make

Say the design "does not add avoidable visual strain". Never write that a design prevents, reduces or cures eye strain, protects the eyes, or is "blue-light safe". Do not describe dark mode, warm tints or special fonts as health features. If the user asks for that kind of copy, explain why and offer the honest wording.

Modes

Read the arguments the skill was invoked with.

  • No argument, or a build task. For a new page or section, study references first (see "Study before you design"). Then apply the rules while you write or edit UI. Start from assets/tokens.css when the project has no color or type tokens yet. When the UI is written, run audit.mjs on the source and inspect.mjs on the rendered page, and go through "What the script cannot see" before you say it is done.
  • audit (optionally followed by a path). Run the script, then review what a script cannot see. Report with the template below. Change nothing.
  • study followed by one or more URLs. Inspect each page and report its design brief: what it does, what is worth borrowing and which comfort rules it breaks. Change nothing.
  • fix (optionally followed by a path). Run the audit. Fix errors, then warnings. Leave a note alone unless fixing an error or warning depends on it, or your own review shows it is a real problem. Re-run the script and report.

Running the script

Run it from the project root and give it the path to check. The script lives in this skill's scripts/ folder, so use the path this skill was loaded from:

node <skill-dir>/scripts/audit.mjs src                 # text report, exit 1 if any error
node <skill-dir>/scripts/audit.mjs src --json          # machine-readable
node <skill-dir>/scripts/audit.mjs src --strict        # exit 1 on warnings too
node <skill-dir>/scripts/audit.mjs contrast "#1f2328" "#ffffff"          # one pair
node <skill-dir>/scripts/audit.mjs contrast "#8a8f98" "#ffffff" --min 3  # a border or icon
node <skill-dir>/scripts/inspect.mjs https://example.com              # design brief and rendered comfort check
node <skill-dir>/scripts/inspect.mjs http://localhost:3000 --out shots # also saves light and dark screenshots
node <skill-dir>/scripts/inspect.mjs dist/index.html --json
  • audit.mjs reads source files. inspect.mjs opens a page in a real browser, so it measures what the reader gets: the contrast of real text on its real background, real characters per line, whether a dark scheme exists and whether motion stops when reduced motion is requested.
  • inspect.mjs works on any URL or local HTML file. It needs Playwright in the project (npm i -D playwright && npx playwright install chromium). If it is missing and you cannot install it, say the rendered check was not run.
  • A path is required. If the user gave none, use the folder that holds the UI source.
  • Colors can be hex, rgb(), hsl(), oklch(), white or black.
  • To silence a finding that is intentional, put a comment containing easy-on-the-eyes-ignore on that line, or easy-on-the-eyes-ignore-next-line on the line before.
  • The script needs Node 18 or later and has no dependencies. If Node is missing, apply the rules by hand and say the script was not run.

Both scripts report under the rule IDs in the table below. Use those same IDs in your report.

Study before you design

Models produce the average of what they have seen, and the average is what people recognize as generated. Looking at specific, shipped work first gives you real decisions to react to.

  1. Pick three to five live sites in the same category as what you are building. Use the ones the user names. Otherwise find them with web search, or with any design-reference or screenshot tool connected to the session.
  2. Run inspect.mjs on each, with --out so you can open the screenshots and look at them.
  3. For each one, note the fonts and type scale, how many colors it uses and where the accent goes, the line length, the section structure, and the one thing that makes it recognizable.
  4. Read the comfort findings for each reference. Admired sites often ship tiny text, weak contrast and heavy motion. Borrow the composition and leave those behind. references/craft.md has the table.
  5. Tell the user which sites you studied and what you took from each. Borrow structure and decisions. Never copy a brand's name, logo, wording, images or exact layout.

If you cannot open any reference, say so and design from the rules and references/craft.md.

Evidence grades

Every rule carries one grade. Repeat the grade when you explain a finding, so nobody mistakes a habit for a fact.

GradeMeaning
researchSupported by controlled studies or systematic reviews
standardSet by a WCAG 2.2 success criterion. The reference file gives the criterion and its level
conventionSensible and widely shipped, but no trial behind it
inferenceDerived from research on a related stimulus, not tested on web pages

Rules

Severity decides the order: errors first, then warnings, then notes. Inside a severity, work down the table. The severity shown is the usual one. The script lowers it when it cannot tell whether a line is a problem (a small size on what may be a label), and you may raise it when your review shows real harm.

IDRuleSeverityGradeReference
type-rem-zoomText must survive zoom. Sizes in rem, no viewport-only font sizes, zoom never disabled.errorstandardtypography
contrast-floorEvery text pair at least 4.5:1. Large text and UI parts at least 3:1.errorstandardcontrast-and-color
contrast-color-aloneNever signal state with color alone.errorstandardcontrast-and-color
motion-flashNothing flashes more than three times a second.errorstandardmotion
motion-autoplayNo autoplay video without controls. Anything that moves for over 5 s beside text needs pause. No endless loops beside text.errorstandardmotion
motion-reducedMovement exists only inside prefers-reduced-motion: no-preference.errorstandardmotion
theme-focusNever remove the focus outline without a visible replacement of at least 3:1.errorstandardtheming
type-body-sizeBody text 1rem minimum, 1.125rem to 1.25rem for long reading. Nothing readable under 0.875rem.warningresearchtypography
motion-triggersNo parallax, scroll hijacking or large-area zoom. Fades and color changes are fine.warningresearchmotion
contrast-dark-secondarySecondary text on dark surfaces at 8.5:1 or better. AA alone reads weak there.warninginferencecontrast-and-color
contrast-saturated-on-darkNo saturated red or blue as small text on dark. Lighter, calmer accents in dark themes.warningresearchcontrast-and-color
lum-section-stepsNo alternating full-bleed dark and white sections. No white embeds or modals in a dark theme.warninginferencelayout-and-patterns
lum-white-flashThemed html background and a color-scheme declaration and meta tag.warningconventiontheming
layout-shiftReserve media dimensions, match fallback font metrics, keep CLS at or under 0.1.warningresearchlayout-and-patterns
contrast-pure-extremesNear-black on near-white, off-white on dark gray. Avoid pure black and pure white as page text and background.warningconventioncontrast-and-color
type-leadingBody line-height 1.5 (1.4 to 1.6). Headings 1.1 to 1.3.warningconventiontypography
type-weightBody weight 400 or more. No 100 to 300 at body sizes.warningconventiontypography
type-aligntext-align: start. No justified body text. Caps for short labels only.warningstandardtypography
layout-targetsPointer targets 24 by 24 CSS px minimum, 44 by 44 for primary actions. Links inside a sentence are exempt.warningstandardlayout-and-patterns
theme-both-schemesShip light and dark and follow prefers-color-scheme. A manual toggle is optional and defaults to system.noteresearchtheming
pattern-stripesNo high-contrast stripes or grids with a 7 to 27 px period over large areas.noteinferencelayout-and-patterns
type-measureReading text capped at 50ch to 60ch, which is about 65 to 78 characters.noteconventiontypography
motion-duration100 to 300 ms, 500 ms ceiling, ease-out for entrances.noteconventionmotion
theme-preferencesHonor prefers-contrast, forced-colors and prefers-reduced-transparency.noteconventiontheming
pattern-clutterOne primary emphasis per view. Few accent colors, sizes and border styles.noteresearchlayout-and-patterns
craft-copySpecific copy. Never invent statistics, testimonials, ratings or client logos.warningconventioncraft
craft-referenceStudy three to five real sites in the same category before designing. Borrow decisions, never copy.noteconventioncraft
craft-one-ideaOne distinctive idea per view. Everything else stays quiet.noteconventioncraft
craft-paletteTinted neutrals and one accent. No indigo or purple gradients, no gradient text.noteconventioncraft
craft-show-productShow the real interface, data or code. No row of three identical icon cards, no emoji icons.noteconventioncraft
craft-layoutDo not center everything. Uneven grid splits and varied section structure.noteconventioncraft
craft-restraintFlat surfaces and hairlines. Few shadows, one radius scale, no stacked blur and glow.noteconventioncraft

Reference files hold the reasoning, sources and before/after code. Read each one that covers a rule you are applying or reporting. A fix across a whole page usually needs three or four of them.

  • references/contrast-and-color.md: choosing colors, building a palette or a dark theme, explaining a contrast finding.
  • references/typography.md: type size, line length, spacing, fonts, fluid type.
  • references/motion.md: animation, transitions, video, scroll effects, loaders.
  • references/layout-and-patterns.md: tables, grids, stripes, density, section backgrounds, images, layout shift.
  • references/theming.md: light and dark themes, a theme toggle, focus styles, user-preference media queries, Tailwind and shadcn/ui.
  • references/craft.md: designing a new page or section, a result that looks templated or generated, what to borrow from a reference site and what to leave.
  • references/evidence.md: when the user asks why, questions a rule, or asks about blue light, dark mode, dyslexia fonts or APCA.

Defaults to write without being asked

:root {
  color-scheme: light dark;
  --bg:     light-dark(oklch(0.985 0.002 90), oklch(0.18 0.01 255));
  --text:   light-dark(oklch(0.24 0.01 255),  oklch(0.93 0.005 255));
  --muted:  light-dark(oklch(0.48 0.01 255),  oklch(0.78 0.01 255));
  --accent: light-dark(oklch(0.5 0.19 255),   oklch(0.74 0.13 255));
}
html { background-color: var(--bg); color: var(--text); }
body { font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); line-height: 1.6; }
p, li { max-inline-size: 55ch; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) {
  .card { transition: transform 200ms ease-out; }
}

Add <meta name="color-scheme" content="light dark"> to the page head.

Body text measures 15.75:1 in light and 15.30:1 in dark. Muted text measures 6.25:1 and 9.39:1. The accent measures 5.78:1 and 8.14:1, which is why it is used for the focus ring: the system Highlight color can fall under 3:1 on a dark surface. assets/tokens.css has the full set, including surfaces, borders for controls, a long-reading size and an opt-in dim theme.

Only add color-scheme: light dark once the page really has colors for both schemes. On a page with hard-coded light colors it gives dark scrollbars and form controls on a white page. Fix theme-both-schemes in the same change.

Tailwind and shadcn/ui ship pure white with near-black (about 19.8:1) and bg-white / text-black as pure values. Override --background and --foreground, and use semantic utilities such as bg-background and text-foreground.

What the script cannot see

inspect.mjs covers the first, third and fifth items below when you can run it on the rendered page. Check the rest, and all of them when it could not run, by reading the code or the page. If you cannot check one, list it under "Not verified" and say why.

  • Contrast of each real text and background pair, including text over images and gradients. Measure pairs with the contrast command
  • Whether small text is body copy or a short label
  • Line length in the rendered layout. Count characters in a few full lines
  • Flash rate of animations and video
  • Brightness jumps between sections and white embeds inside dark themes
  • Layout shift during load, including images and video with no width and height
  • Whether state is carried by color alone
  • JavaScript-driven animation that ignores reduced motion
  • Sizes set in em, percentages or the font shorthand, and stripes built from background-size

Report template

Easy on the Eyes <audit | fix>: <path>

Fixed (N)                      <- fix mode only
  <file>:<line>  <rule-id>  <what changed, one line>

Errors (N)
  <file>:<line>  <rule-id>  [<grade>]
    <offending line, quoted>
    Why: <one sentence>
    Fix: <concrete change>

Warnings (N)
  ...

Notes (N)
  ...

Not verified
  - <check>: <why it could not be checked>

Summary: <the most important thing first. In fix mode, say what is still open and why>

In fix mode, the Errors, Warnings and Notes sections list only what is still open after your changes. Keep each finding to the lines shown. Do not list rules that passed. Your counts may differ from the script's when your own review adds or reclassifies findings. Say so in the summary.

Gotchas

  • WCAG 1.4.12 does not require a line height of 1.5. It requires that the layout survives when a user sets it. Do not use fixed heights on text containers.
  • Passing 4.5:1 is not the same as comfortable in dark themes. #a0a0a0 on #121212 passes at 7.16:1 and still reads weak. Light themes are the opposite: 4.5:1 is the binding limit there.
  • --border style hairlines sit near 1.3:1 and are decoration. Input and control edges need 3:1, so use a stronger border token for them.
  • Do not flag a forced-colors or prefers-contrast: more block for using pure black or white. Maximum contrast is the point of those blocks.
  • Small sizes and tight leading are fine for headings and short labels. The script reports those as notes, or skips them, for that reason.
  • A loading spinner that leaves the DOM when loading ends is not an endless-animation problem.
  • An animated GIF is a script note because the script cannot tell whether it animates. If it loops beside content for more than 5 seconds, report it as a motion-autoplay error.
  • APCA is useful as a second opinion on dark themes, but it is not part of WCAG and its reference code has a restrictive license. Use the APCA readout in Chrome DevTools. Do not copy its source into a project.
  • The craft rules are taste, graded convention. When one disagrees with a comfort rule, the comfort rule wins. Do not report a craft note as if it were a defect.
  • A reference site is evidence of what someone shipped, not proof that it is good. Check it against the comfort rules like any other page.
  • This skill works alongside a WCAG audit. It does not replace one.

Related Skills