jbelly-ui · git:20260917.6b91b0c · 2026-09-17 · sha256 e52d83da4e3d595b
jbelly-ui git:20260917.6b91b0cA
Immutable. This exact content is served forever at /api/v1/blob/e52d83da4e3d595b.
--- name: jbelly-ui license: MIT description: "Licence-free UI system for web apps and sites: build, review or redesign dashboards, admin panels, settings/auth, tables and landing pages with exact tokens, a spec-driven page builder, a pre-flight against AI-default looks, and a mandatory personality step. Not for backend, API or non-visual work." --- # jbelly-ui — the house UI system A complete design system expressed as **rules and recipes**: exact sizes, class strings, behaviours and checklists. Nothing here depends on a purchased template or a per-project licence, so it ships in any number of products. Two layers, and both are mandatory: 1. **Foundation** (shared by every product): semantic tokens, app shell, exact component sizes, admin-grade behaviours. This is what makes a UI feel like a paid template — every state handled, nothing shifts, keyboard works. 2. **Personality** (unique per product): type pairing, palette, shape, density, surface, motion, one signature element. This is what stops every AI-built product from looking like the same site in a different colour. Stack-neutral: tokens are CSS variables, recipes are Tailwind v4 utility strings that map 1:1 to CSS. ## Modes | Mode | Trigger | Path | |------|---------|------| | **Build** | "make / add / create a page, dashboard, form…" | workflow below | | **Review** | "review / critique / audit / does this look professional" | `references/review-rubric.md`: run `scripts/preflight.py` + `scripts/verify_page.py`, score ten dimensions once, report `file:line` rows. No second opinions, no subagents. | | **Redesign** | "restyle / modernise / make it look like…" | `scripts/audit_styles.py` first, then personality, then fix in priority order (fonts → colour → radius/shadow → spacing → states → motion). | **Design read (first output in every mode).** Before any code or verdict, emit four fields and keep them in `design/personality.md`: `kind` (dashboard / settings / landing / …), `audience` (who, how often, keyboard or touch), `vibe` (three words), `system` (preset + dials changed). It is the contract everything else is checked against. ## Workflow **Cost first.** The references total ~28K tokens; every tool call after reading them re-sends them. So: for a standard app screen read only `references/quick-card.md` (~2K tokens) plus the one personality preset you need, in a single batch at the start. Then **generate, do not compose**: write a ~2 KB JSON spec (see `assets/spec.example.json`) and run `python scripts/build-screen.py spec.json out.html` — nav, toolbar, KPIs with sparklines, chart, highlights donut, table with states, activity, i18n all come from the shell for zero model tokens; add only bespoke widgets as `extra_html` or by editing the built file. (For a blank shell use `python scripts/new_screen.py`.) Write once; verify once with `python scripts/verify_page.py <page>` (render + console + lint + pre-flight in one call). Open a full reference only for something the card and scaffold do not cover. Budget: no more than 12 tool calls per screen. Implementation belongs to the cheapest model class that passes the done list (Class B); reserve the top class for the personality decision and the final review. 1. **Choose the personality first** — `references/personalities.md`. Pick the closest preset and change at least two dials, or derive one from the brief. Write it to `design/personality.md` with `python scripts/personality_init.py --product … --kind … --audience … --vibe … --preset … --change … --change …` (or by hand in that format). Never start on the default look; the default exists only so the demo renders. 2. **Install the tokens** — copy `references/tokens.css` into the project, load it right after Tailwind (`@import "tailwindcss"; @import "./tokens.css";`), append the personality overrides. To change a colour later, edit a token, never a component. 3. **Pick a shell** — `references/layouts.md`: app shell (sidebar + header), header-only, auth, or landing. Copy the skeleton. 4. **Build with the recipes** — `references/components.md` for controls, `references/patterns.md` for screens. Every element has a recipe with exact sizes; that is what keeps mixed rows aligned and ten screens coherent. 5. **Wire the behaviours** — `references/ux-behaviours.md`. Loading, empty and error states, table selection and bulk actions, form validation, overlay focus rules, keyboard, persistence. Not optional. 6. **Lint and check** — `python scripts/lint_tokens.py <src-dir>` (or the PowerShell twin `scripts/lint-tokens.ps1`) flags raw palette classes that bypass tokens. Then the done list below. Want to see it first? Open `assets/app-shell.html` — a self-contained page with the shell, the core recipes, dark mode and a personality switcher. Reviewing an existing UI? Run steps 6 → 5 → 1 in that order: lint, then compare behaviours, then ask whether the product has a personality at all. ## The foundation in one screen Everything below is spelled out with exact values in `references/quick-card.md`; this is the shape of it. - **Semantic colour roles, never raw palette**: `background/foreground`, `card`, `popover`, `primary` (the single brand action), `secondary`, `muted`, `accent`, `mono` (strongest text), `destructive/success/warning/info` (always with text or an icon), `border/input/ring`, `sidebar-*`. Roles are redefined once under `.dark` and once per personality; that is why dark mode and re-branding cost nothing. - **Rhythm**: 4px unit; `--radius` per personality (cards +4px, controls −2px, chips −4px); cards `gap-5 lg:gap-7.5`, rows `gap-2.5`; container max 80rem. - **Type**: Inter for display and text by default (weights 400/500/600), UI at 13px, card titles 16px semibold tracking-tight, page title 20px, KPI numbers 30px semibold `tabular-nums`; a display face only for a brand reason. - **Controls share three sizes**: 28 / 34 / 40px high with 12 / 13 / 14px text, so mixed rows always align. Density presets scale them together. - **Elevation nearly flat**: hairline border + `shadow-xs` on cards, buttons, inputs; `shadow-md` on popovers; nothing else. - **Layout**: sidebar 280px (80px collapsed, peeks on hover), header 70px (60px mobile), both fixed; sidebar is a drawer below `lg`; logical properties only, so RTL is `dir="rtl"` and nothing else. - **Charts**: ApexCharts themed from tokens (`references/charts.md`). **Icons**: Lucide 16–20px, stroke 2; never per-project-licensed sets, never emoji. ## Rules - **Colour comes from tokens.** Raw palette classes are allowed in exactly one file: `tokens.css` (and the personality block). The lint enforces this. - **Recipes are HTML class strings.** If you move one into CSS with `@apply`, drop `group` and `peer` (they are markers, not utilities — Tailwind v4 fails the whole stylesheet with "Cannot apply unknown utility class") and write `.parent:hover .child` selectors instead. Always open the page once in a browser (or headless Edge/Chrome with `--screenshot`) before calling it done; a compile error renders as an unstyled page, not as a warning. - **One primary per view.** The brand colour marks the single main action and the active nav item. Everything else is `secondary`, `outline` or `ghost`. - **Cards are the unit of layout**; no cards inside cards — use bordered sections. No bare text on the page background. - **Tables are dense, forms are calm.** Tables 13–14px, ~46px rows, hairline row borders, no zebra. Forms one column, labels above, `gap-5`. - **Every async region has four states**: loading (skeleton), empty (with next action), error (what happened + retry), success. - **Status is never colour alone.** Text or an icon accompanies every colour. - **Dark mode is a class** (`html.dark`), persisted, and every screen is checked in both modes. - **Motion is 150ms ease-out** on colour / opacity / transform; the sidebar collapse is the one 300ms transition; a personality may add **one** signature moment. `prefers-reduced-motion` is honoured by tokens.css. - **Anti-defaults** (the AI-generic tells — refuse them unless the personality chose them on purpose): blue-600 primary · untouched zinc greys · `rounded-2xl shadow-lg` on everything · purple/blue gradients or gradient text · glassmorphism by reflex · icon-in-a-rounded-square on every card · hero + three feature cards · uniform `gap-4 p-6` with no hierarchy · `Sparkles`/`Zap` icons · "Elevate / Seamless / Powerful" copy · emoji as icons · DiceBear avatars. - **Never paste code, CSS, images, fonts or icons from a commercial template** into a product, even one the team owns a licence for — licences are per project and per deployment. Build from these recipes; look at templates only for layout ideas. - **Libraries must be MIT/BSD/Apache-licensed** and styled through tokens — see `references/integrations.md` for the vetted list per need (charts, tables, calendars, editors, uploads, maps, drag-and-drop). ## Working alongside `ui-ux-pro-max` If that skill is installed, it is a catalogue (styles, 192 palettes, 74 font pairings, 119 UX rules); this skill is the system. Use them together like this: run its `--design-system` search **only** to shortlist a type pairing or palette for step 1, then encode the choice as jbelly-ui tokens in `design/personality.md`. Its `MASTER.md` must not define colours that `tokens.css` does not; on any conflict, tokens.css wins. Do not adopt a "style" it names (glassmorphism, neumorphism…) unless the personality dials call for it — that is exactly how products end up looking random. ## Without tools (manual fallback) If scripts cannot run in your environment, do these by hand before finishing: search the markup for raw palette classes and hex colours and replace them with roles; count primary buttons outside the nav (exactly one); give every icon-only button an `aria-label`, add a skip link when there is a nav, keep one `<h1>`; remove purple/indigo gradients, gradient text, Sparkles/Zap icons, emoji icons, `transition: all` and filler words; check text-on-background and white-on-primary contrast (4.5:1 or better); confirm four states per async region; open the page once in light, dark and RTL. ## Reference files | File | Read when | |------|-----------| | `references/quick-card.md` | **First, for any standard app screen**: tokens, sizes and the 20 most-used recipes on one page, plus the cost rules. Usually the only reference you need together with the scaffold. | | `scripts/verify_page.py` (`verify-page.ps1` on Windows) | The one verification call before done: renders variants headlessly (Playwright, or Chrome/Chromium/Edge), reports console errors, runs the token lint, prints PASS/FAIL. Replaces multi-step verify loops. | | `scripts/build-screen.py` + `assets/spec.example.json` | **The default build path**: a small JSON spec in, a complete verified-pattern page out (charts, table states, drawer, palette, i18n included). Edit the output only for bespoke widgets. | | `scripts/new_screen.py` (`new-screen.ps1` on Windows) | A blank copy of the shell with personality, density, direction and dark default set, when the page is unlike a dashboard. | | `references/review-rubric.md` | Review and Redesign modes: ten scored dimensions with evidence, the `file:line` output format, the audit-first protocol. | | `scripts/preflight.py` | Any mode, before done: AI-tells list (gradient purple, gradient text, Sparkles icons, filler copy, emoji icons…), structure checks (one primary, h1, skip link, labelled icon buttons), WCAG contrast of the token pairs. Runs inside `verify_page.py`. | | `scripts/audit_styles.py` | Redesign mode, first: inventory of fonts, colours, radii, shadows, spacing, durations, raw palette classes; prints the deviation list in fix order. | | `references/interface-guidelines.md` | Building or reviewing any control: the exact-value rules for forms, focus, motion, typography, colour, layout, copy, accessibility and performance, restated from the most-used interface guidelines. | | `references/anti-patterns.md` | When a page looks generated, or in Review mode: each tell, why it fails, what to do instead; the marked ones are checked by `preflight.py`. | | `references/stacks.md` | When the project is not Tailwind v4: the same recipes in plain CSS and React; DTCG tokens (`assets/tokens.json`, built by `scripts/export_tokens.py`). | | `references/sources.md` | To check or add a rule: which research, design system or measured run each rule family comes from. | | `references/charts.md` | Any chart: the ApexCharts house theme (from tokens), 8 chart recipes, the rules (heights, legends in card headers, sr-only tables, dark re-render). | | `scripts/personality_init.py` | Step 1: writes `design/personality.md` (the design read + dials) from a preset and the dials you changed; the file every later screen is checked against. | | `references/personalities.md` | Step 1, always. Eight dials, six presets with token overrides, density block, how to derive a new one, the persisted file format. | | `references/tokens.css` | Step 2. Light/dark roles, states, sidebar roles, radius scale, Tailwind v4 `@theme` mapping, base resets, reduced-motion. | | `references/layouts.md` | Step 3. App shell, sidebar nav, header bar, collapse + mobile drawer, page toolbar, grids, settings variants, profile hero, header-only shell, auth pages, landing page order, containers, RTL. | | `references/components.md` | Step 4. Button, input, select, textarea, checkbox, radio, switch, label, badge, avatar, card, table, tabs, dropdown, modal, drawer, alert, toast, tooltip, progress, skeleton, pagination, breadcrumb, kbd, separator, link, empty state — exact class strings. | | `references/patterns.md` | Step 4. KPI cards, callout, chart card, table card with toolbar, list card, progress list, activity feed, notification drawer, settings form, datatable page, pricing, checkout, search palette, cards grid, empty/error states, dashboard blueprint. | | `references/ux-behaviours.md` | Step 5. Navigation, loading & feedback, tables, forms, overlays, keyboard, dashboards, responsive, preferences, copy, behaviour checklist. | | `references/integrations.md` | Any time a screen needs a chart, data grid, calendar, date picker, rich-text editor, file upload, map, drag-and-drop, command palette, toasts, forms/validation, i18n or animation: the licence-safe library per need, how to style it with tokens, and the interaction rules (state layers, motion durations, density steps). | | `references/industry-playbooks.md` | Step 3–4 when the product is a known business type (SaaS, admin/ops, e-commerce, clinic/wellness, restaurant, education, real estate, finance, travel, corporate/agency): the page inventory, the flows, and the patterns buyers of top-selling templates consistently expect. | | `assets/app-shell.html` | A working, self-contained starting point and visual check (dark mode, RTL, personality switcher). | | `scripts/lint_tokens.py` (`lint-tokens.ps1` on Windows) | Step 6. Finds raw palette colours outside the token file. | ## Done list - [ ] `design/personality.md` exists and differs from the default (and from the last product built). - [ ] `tokens.css` loads first; no other file defines `--primary`; lint passes. - [ ] Light, dark, `dir="rtl"`, and 375 / 1024 / 1440px checked. - [ ] Four states per async region; one active nav item; one primary per view. - [ ] Tables: sort, filter chips, pagination text, bulk bar, hover row actions reachable by keyboard. - [ ] Forms: labels above, inline errors, focus to first error, dirty guard. - [ ] Overlays: focus trap, `Esc`, focus return, scroll lock. - [ ] Icons all Lucide/inline SVG; no template assets; no emoji icons; every dependency on the vetted list.