Design with AI
Lazy Implementation Expression

Layout Specification

A constrained subset of React and Tailwind CSS for defining UI layouts as structured instructions for AI.

LLM Written
Human Reviewed

Danger

This is still in development

Layout Specification

This document defines a minimal, deterministic subset of React and Tailwind CSS designed to describe UI layouts as structured instructions for AI. By constraining the available primitives, the spec eliminates ambiguity and keeps the instruction surface small enough for reliable generation and interpretation.

Every token in this spec is intentional. If something isn't listed here, it isn't available.

Elements

The full set of allowed JSX elements. No other HTML or custom components may be introduced unless explicitly defined elsewhere.

ElementPurpose
<div>Generic container and layout wrapper
<p>Text content
<img>Images (requires src, alt)
<Icon>Icon component (library-dependent)
<button>Clickable actions
<select>Dropdown selection
<input type="text">Single-line text input
<input type="checkbox">Boolean toggle
<input type="radio">Single-choice from a group

Variables

State is managed exclusively through React's useState hook. Each variable must declare its type.

const [count, setCount] = useState<number>(0);
const [label, setLabel] = useState<string>('');
const [visible, setVisible] = useState<boolean>(false);
const [config, setConfig] = useState<object>({});
const [items, setItems] = useState<array>([]);

The five types — number, string, boolean, object, array — cover all state needs within a layout. Default values are always provided inline.

className Tokens

All visual styling is expressed through Tailwind utility classes. Only the tokens listed below are valid.

Sizing

Control the dimensions of an element.

TokenBehavior
w-[<number>px]Fixed width in pixels
w-full100% of parent width
h-[<number>px]Fixed height in pixels
h-full100% of parent height
flex-1Grow to fill remaining space

Layout

Arrange children within a container.

TokenBehavior
flexEnable flexbox
flex-rowHorizontal axis
flex-colVertical axis
items-startCross-axis align to start
items-centerCross-axis align to center
items-endCross-axis align to end
justify-startMain-axis pack to start
justify-centerMain-axis pack to center
justify-endMain-axis pack to end
justify-betweenEqual space between children
justify-aroundEqual space around children
gap-<number>Gap between flex children (Tailwind scale)
relativePosition relative to normal flow
absolutePosition relative to nearest relative ancestor
z-<number>Stack order
overflow-autoScroll when content overflows
overflow-scrollAlways show scrollbar
overflow-hiddenClip overflowing content

Spacing

Margin and padding follow Tailwind's numeric scale.

TokenSide
p-<n>All
pt-<n>Top
pr-<n>Right
pb-<n>Bottom
pl-<n>Left
px-<n>Horizontal (left + right)
py-<n>Vertical (top + bottom)
TokenSide
m-<n>All
mt-<n>Top
mr-<n>Right
mb-<n>Bottom
ml-<n>Left
mx-<n>Horizontal (left + right)
my-<n>Vertical (top + bottom)

Styling

A deliberately small palette and typographic scale.

Colors — only three background values are permitted:

  • bg-black
  • bg-white
  • bg-transparent

Borders — applied per-side or to all sides:

  • border, border-t, border-r, border-b, border-l

Typography:

TokenRole
text-xs12px
text-sm14px
text-base16px
text-lg18px
text-xl20px
text-2xl24px
font-normalRegular weight
font-boldBold weight
text-leftLeft-aligned
text-centerCenter-aligned
text-rightRight-aligned

Conditional Rendering

Show or hide elements based on state. All conditions use short-circuit evaluation with &&.

{
  isVisible && <div>Shown when true</div>;
}

{
  count > 0 && <p>Count is positive</p>;
}

{
  status === 'error' && <p>Something went wrong</p>;
}

{
  !isLoading && <div>Content loaded</div>;
}

No ternary expressions. No if/else blocks. A condition is either met and the element renders, or it isn't and nothing renders.

Interaction

State updates are bound directly to onClick. Only two patterns are allowed:

// Set to a specific value
<button onClick={() => setCount(1)}>Reset</button>

// Toggle a boolean
<button onClick={() => setActive(!active)}>Toggle</button>

No inline logic beyond these two forms. Complex interactions should be decomposed into multiple state variables.

Responsive Prefixes

Any className token can be prefixed with a breakpoint to apply conditionally at that viewport width and above.

PrefixMin-width
sm:640px
md:768px
lg:1024px
<div className='flex-col md:flex-row gap-4'>{/* Stacks vertically on mobile, horizontally on tablet+ */}</div>

The data-description Attribute

Any element may carry a data-description attribute containing freeform text. This attribute has no runtime effect — it exists purely as a semantic annotation for AI interpretation.

<div
  className='flex flex-col gap-2'
  data-description='Sidebar navigation that collapses on mobile. Contains 5-8 nav items.'>
  {/* ... */}
</div>

Use data-description to communicate intent, behavior, or context that cannot be expressed through the structural primitives alone. Think of it as a comment that travels with the element.

data-description is for intent and context, not for styling instructions or logic. Keep it declarative: describe what something is or why it exists, not how to build it.

Design Principles

This spec is shaped by a few deliberate constraints:

  1. Closed set. Every valid token is enumerated. There is no escape hatch into the full Tailwind or React API.
  2. Flat state. useState with primitive types keeps state predictable and serializable.
  3. No logic. No ternaries, no loops, no computed values. Conditions are binary. Interactions are assignments or toggles.
  4. Semantic hints over code. data-description lets you annotate intent without expanding the executable surface.

The goal is a language that is small enough for an AI to handle reliably, and expressive enough to describe real layouts.

On this page