gholtzap/lintapple

It should be impossible for AI to make a bad UI.

JavaScript

431

37 commits

updated Oct 12, 2026

See the code

See what people are saying

SourceMessageScoreDate

Lintapple: UI checks for AI-generated interfaces

1

Oct 12, 2026

README

lintapple logo

lintapple

It should be impossible for AI to make a bad UI.

npm · Demo

Install

Requires Node.js 22 or later. Run in your app’s project directory:

npm install -D lintapple && npx lintapple init

This creates ui-policy.json and a lint:ui script. Existing settings are kept. Set the fonts and text sizes in ui-policy.json to match your app. Set the app URL in the lint:ui script; the default is http://localhost:3000.

Use

Start your app, then run:

npm run lint:ui

Each finding includes the rule, element, measured value, and suggested fix. Exit codes: 0 passed, 1 findings, 2 check did not finish.

To check another URL or save a JSON report:

npx lintapple http://localhost:3000 --json

For a page that loads asynchronously, add --ready '[data-app-ready]' with a selector that is visible when the page is ready.

Use in Playwright

Add this to an existing test after the page is ready:

import { expectUI } from 'lintapple/playwright';

await expectUI(page, testInfo);

Findings fail the test and attach a JSON report. The helper reads your ui-policy.json. See the example tests.

Mark layout elements

Font, contrast, control size, and screen bounds checks work without extra markup. Add these attributes for checks that need layout information:

AttributeUse on
data-ui-stackA group whose child spacing must be checked.
data-ui-actionsA button group whose gaps must be checked.
data-ui-containerA surface whose button insets must be checked.
data-ui-numberA changing number that needs equal digit widths.
data-ui-contentA container whose text must stay inside its edges.
data-ui-align="start"A group whose marked elements must align. Use center or end for other alignments.
data-ui-align-itemEach element to compare in an alignment group.
data-ui-radiusAn outer surface with equal corner radii and insets.
data-ui-radius-innerIts direct inner surface. Its radius must equal the outer radius minus the inset.

You can also use controlContainers in the policy to select existing button containers. See example styles.

License

MIT. See LICENSE.

gholtzap/lintapple

It should be impossible for AI to make a bad UI.

JavaScript

431

37 commits

updated Oct 12, 2026

See the code

See what people are saying

SourceMessageScoreDate

Lintapple: UI checks for AI-generated interfaces

1

Oct 12, 2026

README

lintapple logo

lintapple

It should be impossible for AI to make a bad UI.

npm · Demo

Install

Requires Node.js 22 or later. Run in your app’s project directory:

npm install -D lintapple && npx lintapple init

This creates ui-policy.json and a lint:ui script. Existing settings are kept. Set the fonts and text sizes in ui-policy.json to match your app. Set the app URL in the lint:ui script; the default is http://localhost:3000.

Use

Start your app, then run:

npm run lint:ui

Each finding includes the rule, element, measured value, and suggested fix. Exit codes: 0 passed, 1 findings, 2 check did not finish.

To check another URL or save a JSON report:

npx lintapple http://localhost:3000 --json

For a page that loads asynchronously, add --ready '[data-app-ready]' with a selector that is visible when the page is ready.

Use in Playwright

Add this to an existing test after the page is ready:

import { expectUI } from 'lintapple/playwright';

await expectUI(page, testInfo);

Findings fail the test and attach a JSON report. The helper reads your ui-policy.json. See the example tests.

Mark layout elements

Font, contrast, control size, and screen bounds checks work without extra markup. Add these attributes for checks that need layout information:

AttributeUse on
data-ui-stackA group whose child spacing must be checked.
data-ui-actionsA button group whose gaps must be checked.
data-ui-containerA surface whose button insets must be checked.
data-ui-numberA changing number that needs equal digit widths.
data-ui-contentA container whose text must stay inside its edges.
data-ui-align="start"A group whose marked elements must align. Use center or end for other alignments.
data-ui-align-itemEach element to compare in an alignment group.
data-ui-radiusAn outer surface with equal corner radii and insets.
data-ui-radius-innerIts direct inner surface. Its radius must equal the outer radius minus the inset.

You can also use controlContainers in the policy to select existing button containers. See example styles.

License

MIT. See LICENSE.