v1.0.8

Design principles

The rules Veritheme is built on — and the same rules its MCP server enforces when AI generates UI with it.

One rulebook for humans and AI

These principles govern every Veritheme surface: the components themselves, the docs and examples, the Figma library — and AI output through the MCP server, which carries them as generation rules.

AI-ready by design

Connect npx -y @veritheme/mcp-server and generated UI follows this page automatically — component choice, type scale, spacing grid, color roles, composition patterns.

The principles

Hard rules are enforced (build guards on this site, generation rules in MCP). Soft ones are followed for polish.

Semantic-first

Guideline

The token and class names are the design intent — match the meaning of the content to the name instead of picking by how something looks. success = positive/confirmation, warning = caution, error/danger = failure or destructive, info = neutral notice and focus, accents-brand = the product’s own accent. mains steps primary → quaternary from most to least important; surfaces name elevation; typography classes name role. The rules below are the guardrails; choosing the semantically-correct token is the goal.

Component-first

Rule

If a component exists for the element, use its classes — never rebuild it from utilities, and never override a component’s size or colors with utilities (pick the proper variant instead). Utilities are for layout only: flex, grid, gap, spacing, max-width.

Minimum text size is 12px

Rule

Nothing renders below the xs token (12px) — even Overline is 12px; there is no 11px in the scale. At 12px, prefer the semantic class over a raw size: vt-caption for fine print, vt-text-overline for uppercase eyebrows, vt-section-label for group labels.

Spacing lives on the grid

Rule

Paddings, margins, gaps and sizes come from the spacing scale only. No arbitrary pixel values — if a step feels missing, snap to the nearest one. Rhythm: mt-8 between page sections, gap-4–6 between cards, gap-2–3 inside groups.

Color comes from tokens

Rule

No hex, no rgb, no inline styles. Interactive and accent elements use accents-brand; blue info-* is reserved for informational states and focus. Surfaces follow the hierarchy (background → surface → subtle → moderate) so dark mode works automatically. Text steps down mains-primary → secondary → tertiary → quaternary; intent colors only mean their state.

Radii from the scale — concentric when nested

Guideline

Corner radii come from the radius scale. When a rounded element sits inside a rounded container, prefer inner radius = parent radius − padding so the corners run parallel (vt-rounded-concentric-3 inside a p-3 card). An aesthetic guideline, not a law — skip it when it fights the layout.

Start from a proven composition

Guideline

Full screens start from a pattern, the way a designer starts from a known layout: content column max-w-5xl px-6 py-8, app header h-16, sidebar with section labels. The examples gallery is the pattern library — the MCP server serves the same skeletons to AI via list_patterns / get_pattern.

Design the states, not just the happy path

Guideline

Every list, table and board gets an empty state (icon, one line, primary action). Loading is a skeleton shaped like the content. Long text truncates. Destructive actions confirm via dialog. One primary button per view.

Write like a product

Guideline

Sentence case everywhere — buttons, labels, headings. No lorem ipsum: realistic names, dates, sizes and trends. Labels are one to three words. No exclamation marks.

Accessible by default

Guideline

Focus states stay. Icon-only controls carry an aria-label. Images get meaningful alt text. Text/surface pairs from the color hierarchy keep contrast at AA.

Common mistakes

The frequent failure modes — what the rules above exist to prevent.

Rebuilding a component from utility classes

A component almost always exists — use vt-badge, vt-btn, vt-avatar… Utilities are for layout only.

Overriding a component’s size or color with utilities

Pick the variant/size class (vt-btn-sm, vt-badge-soft) instead of vt-text-sm / vt-bg-* on the component.

Using blue info-* for primary actions or accents

Interactive and accent elements are accents-brand; info-* means informational state and focus only.

Intent colors as decoration (a blue heading, green divider)

success/warning/error/info carry meaning — use mains-* and surfaces-* for neutral UI.

Text below 12px, or arbitrary spacing / radius values

Everything comes from the scale: vt-text-xs and up, spacing steps, radius scale — no [13px].

Nesting a card inside a card

Divide card content with spacing or separators; page sections are spacing-separated, not boxes-in-boxes.

Hardcoded white / grey backgrounds

Use the surface hierarchy (surfaces-background → surface → subtle → moderate) so dark mode just works.

Icon-only buttons with no label, or removed focus rings

Every icon-only control gets a title/aria-label; never remove focus-visible styling.

More than one primary button per view

One vt-btn-primary; secondary actions use bordered or ghost.

A list, table or board with no empty state

Design the empty state (vt-empty-state) and the loading state (vt-skeleton) too, not just the happy path.