@selorax/design-quality
v0.1.2
Published
SeloraX design-quality layer — pure slop linter, brand-aware lint (palette + fonts + WCAG contrast), k-means palette extractor, and craft rule docs. Build-time/runtime-pure (no DB, no network, no LLM).
Downloads
325
Readme
@selorax/design-quality
Pure design-quality engine for the SeloraX Pages platform. Catches AI-slop and brand-contract violations in HTML at save time — no DB, no network, no LLM.
npm i @selorax/design-quality0.1.1 · pre-1.0.
What it is
A small, deterministic library that takes a string of HTML and returns design findings:
- Slop linter (Spec 1) — high-confidence anti-patterns AI authors fall into: indigo/violet accents, two-stop "trust" gradients, emoji-as-icon, invented metrics ("10× faster"), card-with-left-accent dashboard tiles, filler copy ("Lorem ipsum"), system sans on display headings.
- Brand-aware lint (Spec 2) — when you pass a tenant's
selorax.design.mdbrand contract:off-palette-hex— hex codes outside the declared paletteoff-brand-font—font-familydeclarations outside the declared fonts
- WCAG contrast (always-on) — inline
color/backgroundpairs failing AA (< 4.5:1). - Craft prompt — concatenates the bundled
craft/*.mddocs into one system-prompt section for AI authoring. - Palette extractor — k-means++ over raw RGBA bytes (e.g. from a logo) so you can seed a brand palette from real data.
- Contrast helpers —
parseHex,relativeLuminance,contrastRatio,wcagLevel.
Used by the backend (POST /pages advisory lint), the editor agent (self-correction loop), the MCP write tools, and the editor's BrandView panel. You normally get it transitively; install it directly only if you're building tooling on top.
Pure. No DB, no network, no LLM, no fs writes. Reads
craft/*.mdfrom its own package dir viafs.readFileSynconce. Safe to run in any environment.
Usage
const dq = require('@selorax/design-quality');
// 1. Slop-only lint
const findings = dq.lint('<h1 style="color:#6366f1">🚀 Hi</h1>');
// → [{severity:'P0', rule:'no-indigo-accent', ...}, {severity:'P0', rule:'no-emoji-icons', ...}]
// 2. Brand-aware lint (palette + fonts from selorax.design.md)
const brand = dq.parseBrandTokens(designMd);
const all = dq.lint(html, {
tokens: brand.palette, // off-palette-hex on
fonts: Array.from(dq.allowedFontFamilies(brand)), // off-brand-font on
});
// 3. WCAG contrast (always-on — no opts needed)
dq.contrastRatio('#ffffff', '#ffd0c0'); // → 1.40
dq.wcagLevel(1.40); // → 'fail'
// 4. Palette from a logo (k-means)
// Decode PNG/JPG via sharp / canvas / etc, then:
const palette = dq.extractPalette(rgbaBytes, { k: 5 });
// → [{hex:'#ff5733', weight:0.62, rgb:[255,87,51]}, ...]
// 5. Craft prompt for the AI system message
const prompt = dq.buildCraftPrompt();API
| Export | Kind | Purpose |
|---|---|---|
| lint(html, opts?) | function | Returns Finding[]. P0/P1/P2 severities. |
| parseBrandTokens(md) | function | Parses YAML frontmatter from selorax.design.md. |
| paletteHexSet(tokens) | function | Set of allowed #rrggbb from tokens.palette. |
| allowedFontFamilies(tokens) | function | Set of allowed font families from tokens.fonts. |
| extractPalette(rgba, opts?) | function | k-means++ over raw RGBA pixel bytes. |
| parseHex / relativeLuminance / contrastRatio / wcagLevel | functions | WCAG 2.x helpers. |
| buildCraftPrompt() | function | Concatenates CRAFT_FILES from CRAFT_DIR into one prompt string. |
| CRAFT_DIR, CRAFT_FILES | const | Absolute path + filename list. |
Full type definitions in dist/index.d.ts.
Graceful degradation
Every consumer in the SeloraX stack lazy-requires this package — if it isn't installed, lint returns [] and the save still happens. lint(html, opts) never throws; malformed input yields [] rather than an error. This is intentional: design quality is always advisory, never blocking.
Tests
bunx vitest run — 101 unit + integration tests.
License
UNLICENSED (private use within SeloraX).
