LIE — The Constrained Language That Makes AI Generate Better UI
AI generates more reliable UI when given a constrained vocabulary. LIE (Layout Implementation Expression) is a minimal subset of React and Tailwind designed exactly for this.

The Problem With Open-Ended Generation
Ask AI to "build a dashboard layout" and it might use CSS Grid, or CSS Flexbox, or a CSS framework you don't use, or inline styles, or a mix of all of them. It might reach for components you don't have. It might invent abstractions that don't match your codebase.
Open-ended generation is unpredictable. The quality varies. The output is hard to integrate consistently.
The solution is constraints.
What is LIE?
LIE (Layout Implementation Expression) is a minimal, deterministic subset of React and Tailwind CSS. It defines a closed vocabulary — a small set of elements, state types, interaction patterns, and style utilities — that AI can use reliably.
When you tell AI to generate UI using LIE, it has fewer decisions to make. Fewer decisions means more consistency.
The Allowed Elements
LIE uses only these HTML elements:
<div>— layout containers<p>— text content<img>— images<Icon>— from an icon library<button>— interactive triggers<select>— dropdown selectors<input>— text, checkbox, radio
That's it. No <span>, no <ul>/<li>, no <table>, no semantic elements. Everything is built from this small set.
State: Flat and Simple
LIE allows four state types via useState:
- number — for counts, indices, quantities
- string — for text input, selected values
- boolean — for toggles, visibility flags
- object — for grouped related state
- array — for lists of items
No reducers, no context, no derived state. If you need it, it's probably an organism that should be broken into smaller components first.
Interaction: Two Patterns Only
LIE allows exactly two onClick patterns:
Set a specific value:
onClick={() => setState('value')}Toggle a boolean:
onClick={() => setState(!state)}No complex event handlers, no async operations, no side effects. Interaction is pure state manipulation.
Conditional Rendering: Only &&
LIE allows one conditional pattern:
{condition && <div>...</div>}No ternaries, no if/else blocks. If you need to show something conditionally, use &&. If you need to switch between two views, that's two separate components.
Sizing: A Closed Set
Rather than arbitrary pixel values, LIE uses a closed set of sizing tokens:
w-[Npx]/h-[Npx]— fixed dimensionsw-full/h-full— fill containerflex-1— take remaining space
Combined with Tailwind's spacing scale for padding and gap, this produces consistent, readable layouts.
data-description: Semantic Hints
LIE introduces a data-description attribute for annotating elements with semantic meaning:
<div data-description="user profile card" className="flex gap-4 p-4">This is a comment for the AI — a way to tell the model what a container represents without adding actual code comments that bloat the output. It keeps structure readable and helps AI maintain intent across edits.
Why Constraints Help AI
This seems counterintuitive. Why would giving AI fewer options produce better results?
Because a closed vocabulary means every decision the AI makes is from a finite, known set. The model can't accidentally reach for something outside the vocabulary. The output is predictable, consistent, and easy to review.
It's the same reason design systems work: a closed set of components produces more coherent interfaces than infinite freehand design.
LIE is a design system for AI generation — not for what gets shipped, but for the intermediate artefact between design intent and production code.