Proper UI

Quality

What is actually verified about Proper UI, how it's verified, and what is not — release status, CI checks, clean-room installs, accessibility scope, and known gaps, dated and sourced.

Why this page exists

Adjectives like "battle-tested" or "production-ready" don't tell you anything you can check. This page replaces them with what is actually run, where it runs, and what it does not cover — every number below is quoted from a file in this repository, not typed by hand. When a number changes, this page is regenerated from the same sources.

Last verified: 2026-09-10. This page is updated per release, not on a fixed schedule — if a section describes a script or job that no longer matches main, open an issue.

Release status

@properui/ui0.1.0
properui (CLI)0.1.0
Registry entries797
Component groups (published layers)69
Component groups (all layers, incl. foundations/examples)106
Marketing section variants446
Page examples (marketing + app)233 (105 marketing, 128 app)
Test suites with an axe assertion118

Counts are quoted from packages/registry/dist/stats.json, which the registry build (pnpm registry:build) generates — they are not hand-maintained.

Supported ranges

Read from packages/ui/package.json and packages/cli/package.json:

  • React: ^19 (react, react-dom peer dependencies of @properui/ui)
  • Next.js: ^15.1.0 (optional peer dependency — next is marked optional, since the library also supports Vite)
  • Tailwind CSS: ^4.3.0 (peer dependency)
  • Node.js: >=20 (engines.node in packages/cli/package.json; @properui/ui declares no engines field of its own)

@properui/ui ships source TSX, not a bundled build — see Known limitations.

What CI verifies on every PR

Two jobs run on every pull request and on every push to main, defined in .github/workflows/ci.yml:

verify

  1. pnpm install --frozen-lockfile
  2. pnpm type-check
  3. pnpm lint
  4. pnpm prettier:check
  5. pnpm test — unit and component tests across the workspace, including the 118 axe suites described on the Accessibility page
  6. pnpm check:assets
  7. pnpm build
  8. pnpm build-storybook

clean-room (timeout 20 minutes)

  1. pnpm install --frozen-lockfile
  2. pnpm test:clean-room

Neither job's failure is soft — both must pass before a PR can merge. release.yml (publishing to npm via Changesets) and deploy-docs.yml (deploying apps/docs to Cloudflare Workers) run separately, only on pushes to main, and don't gate a PR.

Clean-room installs

scripts/clean-room.ts (run as pnpm test:clean-room, the clean-room CI job above) proves the documented install path works end to end, not just in a fixture:

  • Scaffolds a blank app with the framework's own official CLInpm create vite@latest -- --template react-ts and npx create-next-app@latest, not a checked-in template.
  • Runs properui init against the freshly scaffolded app, then properui add badges alerts social-proof-sections use-clipboard and properui add example settings-17 against the built registry (packages/registry/dist) — no shortcuts, no mocked network calls.
  • Lets the real npm install for each component's dependencies happen, including the @properui/icons npm-alias install (npm:@untitledui/icons@^0.0.22) that a plain "does the file exist" check wouldn't catch.
  • Asserts no dangling @/-aliased imports were left behind, then runs the scaffolded app's own npm run build (and tsc --noEmit where a tsconfig.json exists).
  • Repeats the entire sequence for both Vite and Next.js.

This runs on every PR via the clean-room job in .github/workflows/ci.yml. It is a release test, not a documentation footnote: if the CLI or registry regresses in a way that breaks a real install, this job fails before merge.

Accessibility

Every one of the 118 component test suites in packages/ui/src/components renders each documented variant through axe-core and asserts zero detected violations, on every PR. That is a real, narrow claim — not "fully accessible." It doesn't cover meaningful alt text, focus-order sensibility, contrast (jsdom has no layout engine), screen-reader announcement quality, or keyboard operability beyond static ARIA, and no manual assistive-technology audit has been performed yet. See Accessibility for the full scope, what React Aria provides underneath the axe suites, and the manual verification matrix — that page is the source of truth for this claim; this section doesn't repeat it.

Visual quality

Screenshot tooling exists (scripts/shot.ts, run as pnpm docs:shot <slug> or pnpm docs:shot --all) and pixel-diffing against a reference set exists (scripts/diff-shots.ts, run as pnpm docs:diff) for one-off parity checks against a local run of the docs site.

Alongside those, a curated visual regression baseline is committed and checked on every PR: pnpm visual:baseline (scripts/visual-baseline.ts) captures ~25 routes spanning docs, integrations, base components, application examples and marketing pages — not the full ~1,720-page surface — into tests/visual/baseline/, and pnpm visual:check (scripts/visual-check.ts) re-captures and diffs against it, exiting non-zero past the threshold. The visual job in .github/workflows/ci.yml runs the check against a built, served docs site on every PR. See tests/visual/routes.ts for the exact route list.

DimensionValues
Viewport1280×800 desktop and 390×844 mobile (tests/visual/routes.ts) — separate from scripts/shot.ts's own 1600×1000
ThemeLight, dark (toggled via the dark-mode class)
DirectionLTR everywhere, plus dir="rtl" on a handful of routes (a form-heavy page, a dashboard, a marketing hero) — see Known limitations for the scope of RTL coverage itself

scripts/visual-check.ts treats anything above roughly 8% differing pixels, or a size mismatch, as a layout regression (CHECK in its output, with a diff image written to the gitignored tests/visual/.diff/); smaller deltas are expected content differences and marked ok. scripts/diff-shots.ts uses the same ~8% cutoff for its own ad hoc, full-site comparisons, which still have no committed baseline under docs/spec/reference/screenshots.

Agent compatibility

Proper UI documents a workflow for the following coding tools. "Documented" means a page under apps/docs/content/integrations exists with concrete setup steps; "automated test" means CI runs that exact workflow end to end, not just that the underlying CLI works (which the clean-room job above does verify, framework-scaffolding side).

ToolDocumented?Automated end-to-end test?
Claude CodeYes (integrations/claude.mdx)No — not yet
CodexYes (integrations/codex.mdx)No — not yet
CursorYes (integrations/cursor.mdx)No — not yet
Gemini CLIYes (integrations/gemini.mdx)No — not yet
v0Yes (integrations/v0.mdx)No — not yet
Bolt.newYes (integrations/bolt.mdx)No — not yet
LovableYes (integrations/lovable.mdx)No — not yet
ReplitYes (integrations/replit.mdx)No — not yet
MCP serverPlanned, not built (integrations/mcp.mdx describes the intent)No — nothing to test yet

None of these tool-specific workflows has an automated end-to-end test today. The clean-room job (above) verifies the underlying init/add CLI path against real Vite and Next.js scaffolds, which every one of these integrations builds on, but it does not drive Claude Code, Codex, Cursor, or any of the other tools themselves.

Known limitations

Sourced from ROADMAP.md, which exists specifically so nothing in the docs promises what the code doesn't do yet:

  • RTL coverage is incomplete. Logical properties (ms-*, pe-*, text-start) are the house rule, but the port is partial: roughly 281 logical spacing utilities against 365 physical ones across packages/ui/src/components. Base components are further along; marketing sections and page examples carry most of the remaining physical values. Storybook also has no direction toggle yet.
  • No committed visual regression baseline. Covered above — the tooling exists, the baseline and CI comparison do not.
  • No variant gallery thumbnails. Every variant gallery card renders a neutral placeholder; pnpm shots:thumbs generates real thumbnails but none are committed yet.
  • No bundled build. @properui/ui ships source TSX; consumers whose bundler won't transpile a dependency need transpilePackages (Next.js) or their own pipeline (Vite). packages/ui has no build script.
  • No MCP server. The CLI is the supported path today; an MCP server is planned but not built (integrations/mcp.mdx).
  • cssVars is reserved but unused. Every registry entry carries an empty cssVars array — components rely entirely on the shared token file, so there's nothing to merge yet.
  • No manual accessibility audit. See the Accessibility manual verification matrix — every row reads "Not yet verified."

How to reproduce

Every command below is exactly what CI runs — nothing hidden, nothing sequenced differently for a human reader:

# Install
pnpm install --frozen-lockfile

# What the `verify` CI job runs, in order
pnpm type-check
pnpm lint
pnpm prettier:check
pnpm test
pnpm check:assets
pnpm build
pnpm build-storybook

# What the `clean-room` CI job runs
pnpm test:clean-room

# Regenerate the counts quoted on this page (registry build + stats)
pnpm registry:build

# Visual tooling (no committed baseline to diff against yet — see above)
pnpm docs:shot --all
pnpm docs:diff --all --report reports/visual-parity.md

FAQs