This guide enables LLMs to generate valid Wire-DSL files from text descriptions or wireframe images.
Your role: Generate a valid .wire file based on user input.
Output format: Return ONLY valid .wire code block. No explanations, no markdown formatting (except code fence).
Quality requirements:
- Syntax must be 100% valid per Wire-DSL grammar
- All referenced components must exist
- All property values must be valid for their types
- Layouts must be properly nested and closed
- Use sensible defaults when details are missing
Every .wire file must have:
project "ProjectName" {
style {
density: "normal"
spacing: "md"
radius: "md"
stroke: "normal"
font: "base"
}
screen ScreenName {
layout stack(...) { ... }
}
}
- Screen names must be in
CamelCase - Each screen must have a unique name
- Screen names are case-sensitive
- Every screen must have exactly ONE root layout
- Valid layouts:
stack,grid,split,panel,card,tabs - Layouts can be nested inside other layouts
Layout Purposes:
stack- Linear vertical or horizontal stacking of elementsgrid- Multi-column responsive layout (12-column system)split- Two-panel layout with one fixed side + one flexible sidepanel- Container with automatic border, padding, and backgroundcard- Vertical container ideal for product/profile cards with rounded cornerstabs- Tabbed content container; children must betab { }blocks
- Property format:
propertyName: value - String values use double quotes:
"string value" - Numeric values without quotes:
12 - Boolean properties without quotes:
true,false - Enum values without quotes:
primary,horizontal,md
Critical Change (v2+):
- Layouts without explicit
paddinghave 0px padding (not default) - Grid cells without explicit
paddinghave 0px padding - Use explicit padding values:
padding: md,padding: lg, etc.
Valid values: none, xs, sm, md, lg, xl
These define visual consistency across the entire wireframe.
style {
density: "normal" // compact | normal | comfortable
spacing: "md" // xs | sm | md | lg | xl
radius: "md" // none | sm | md | lg | full
stroke: "normal" // thin | normal | thick
font: "base" // sm | base | lg
}
| Value | Pixels |
|---|---|
| xs | 4px |
| sm | 8px |
| md | 16px |
| lg | 24px |
| xl | 32px |
| Component | Required Props | Optional Props | Example |
|---|---|---|---|
Heading |
text |
level, spacing, variant |
component Heading text: "Page Title" level: h2 variant: primary |
Text |
content |
- | component Text text: "Body text" |
Label |
text |
- | component Label text: "Field label" |
| Component | Key Properties | Example |
|---|---|---|
Input |
label, placeholder, size |
component Input label: "Email" placeholder: "your@email.com" size: md |
Textarea |
label, placeholder, rows |
component Textarea label: "Message" rows: 4 placeholder: "Your message..." |
Select |
label, items, size |
component Select label: "Role" items: "Admin,User,Guest" size: md |
Checkbox |
label, checked |
component Checkbox label: "I agree to terms" checked: false |
Radio |
label, checked |
component Radio label: "Option A" checked: true |
Toggle |
label, enabled |
component Toggle label: "Enable notifications" enabled: false |
| Component | Key Properties | Valid Placeholders | Example |
|---|---|---|---|
Image |
type, height |
"landscape", "square", "portrait", "avatar", "icon" |
component Image type: square height: 250 |
Icon |
type |
size, variant |
component Icon icon: "search" size: md variant: primary |
| Component | Key Properties | Example |
|---|---|---|
SidebarMenu |
items, active |
component SidebarMenu items: "Home,Users,Settings" active: 0 |
Tabs |
items, active |
component Tabs items: "Profile,Settings,Activity" active: 0 |
Breadcrumbs |
items |
component Breadcrumbs items: "Home,Users,Detail" |
Topbar |
title, subtitle |
icon, actions, user, avatar, variant |
| Component | Key Properties | Example |
|---|---|---|
Table |
columns, rows |
actions, caption, pagination, paginationAlign, captionAlign |
Stat |
title, value |
component Stat title: "Total Users" value: "1,234" |
List |
items, title |
component List items: "Item 1,Item 2,Item 3" |
Heading- Large titlesText- Body text (short or multi-line)Label- Form labels
Input- Single-line input fieldTextarea- Multi-line inputSelect- Dropdown selectorCheckbox- Boolean selectionRadio- Single selection from groupToggle- Boolean switch
Button- Primary action buttonIconButton- Icon-based button
Topbar- Top navigation barSidebarMenu- Vertical navigation sidebarSidebar- Side navigation panelBreadcrumbs- Navigation path displayTabs- Tabbed content switching
Table- Multi-row tabular dataList- Item list
Image- Static imageIcon- Scalable icon
Divider- Visual separatorSeparate- Invisible spacerBadge- Status indicatorLink- Hypertext linkAlert- Information message
Stat- Metric displayCard- Generic content cardCode- Code snippetChart- Chart area
Modal- Dialog overlay
component Button
text: "Click me" // Display text
variant: "primary" // Visual variant (default | primary | secondary | success | warning | danger | info)
size: "md" // Size (sm | md | lg)
labelSpace: true // Optional control alignment helper
padding: "md" // Optional horizontal inset (none | xs | sm | md | lg | xl)
layout stack(
direction: "vertical" // vertical | horizontal
gap: "md" // xs | sm | md | lg | xl
padding: "lg" // xs | sm | md | lg | xl | none
align: "center" // left | center | right | justify
)
layout grid(
columns: 12 // Number of columns (1-12)
gap: "md" // Space between cells
)
// Grid cells support:
cell span: 8 align: "end" { ... } // span: 1-12, align: start|center|end
layout panel(
padding: "md" // xs | sm | md | lg | xl
background: "white" // Background color
)
layout card(
padding: "md" // xs | sm | md | lg | xl (default: md)
gap: "md" // xs | sm | md | lg | xl (default: md)
radius: "md" // xs | sm | md | lg (default: md)
border: true // true | false (default: true)
)
layout split(
left: 260 // Fixed left panel width (or use right: <number>)
background: "accent" // Optional fixed-panel background color
border: true // Optional vertical divider
gap: "md" // Space between panels
padding: "md" // Optional inner padding
)
project "Admin Dashboard" {
style {
density: "normal"
spacing: "md"
radius: "md"
stroke: "normal"
font: "base"
}
screen Dashboard {
layout split(left: 260, gap: md) {
layout stack(direction: vertical, gap: md, padding: md) {
component Heading text: "Menu"
component SidebarMenu items: ["Dashboard", "Users", "Settings"]
}
layout stack(direction: vertical, gap: md, padding: lg) {
layout grid(columns: 12, gap: md) {
cell span: 4 {
layout card(padding: md, gap: md) {
component Heading text: "Total Users"
component Stat value: "1,234"
}
}
cell span: 4 {
layout card(padding: md, gap: md) {
component Heading text: "Revenue"
component Stat value: "$45.2K"
}
}
cell span: 4 {
layout card(padding: md, gap: md) {
component Heading text: "Growth"
component Stat value: "12%"
}
}
}
layout card(padding: lg, gap: md) {
component Heading text: "Recent Activity"
component Table
columns: "User,Action,Date"
rows: 5
}
}
}
}
}
-
Use token values (spacing, sizing, gaps)
gap: "md" // ✅ Good gap: 16 // ✅ Also valid -
Use meaningful names for screens
screen UserDashboard { ... } // ✅ Clear -
Nest layouts for complex structures
layout stack { layout grid { ... } layout card { ... } } -
Use appropriate container types
layout grid(columns: 12) { ... } // ✅ Grid for multi-column layout stack { ... } // ✅ Stack for linear
-
Invent non-existent components
component FakeComponent { ... } // ❌ Invalid -
Mix property syntaxes
component Button "Click me" // ❌ Missing `text:` -
Leave layouts empty
layout stack { } // ❌ Empty layout -
Use undefined color names
color: "ultraviolet" // ❌ Not a valid color token
layout card(padding: lg, gap: md, radius: lg, border: true) {
component Image type: square height: 250
component Heading text: "Product Title"
component Text text: "Product description"
layout stack(direction: horizontal, gap: md) {
component Button text: "View Details" variant: primary
component Button text: "Add to Cart" variant: secondary
}
}
layout stack(direction: vertical, gap: md, padding: lg) {
component Heading text: "Dashboard Overview"
layout grid(columns: 12, gap: md) {
cell span: 4 {
layout card(padding: md, gap: md) {
component Heading text: "Users"
component Stat title: "Total" value: "1,234"
}
}
cell span: 4 {
layout card(padding: md, gap: md) {
component Heading text: "Revenue"
component Stat title: "Monthly" value: "$45.2K"
}
}
cell span: 4 {
layout card(padding: md, gap: md) {
component Heading text: "Growth"
component Stat title: "YoY" value: "12%"
}
}
}
}
layout split(left: 260, gap: md) {
layout stack(direction: vertical, gap: md, padding: md) {
component Heading text: "Menu"
component SidebarMenu items: "Dashboard,Users,Settings"
}
layout grid(columns: 12, gap: md, padding: lg) {
cell span: 8 {
component Heading text: "Main Content"
component Table columns: "Name,Email,Status" rows: 5
}
cell span: 4 {
layout panel(padding: md, background: "white") {
layout stack(direction: vertical, gap: md) {
component Heading text: "Filters"
component Input label: "Search" placeholder: "Filter..."
component Select label: "Status" items: "Active,Inactive"
component Button text: "Apply" variant: primary
}
}
}
}
}
layout split(left: 280, gap: md) {
layout stack(direction: vertical, gap: md, padding: lg) {
component Heading text: "Profile"
component SidebarMenu items: "General,Security,Privacy" active: 0
}
layout stack(direction: vertical, gap: lg, padding: lg) {
layout card(padding: lg, gap: md, radius: lg, border: true) {
component Image type: square
component Heading text: "John Doe"
component Text text: "john@example.com"
component Divider
component Text text: "Senior Software Engineer"
layout stack(direction: horizontal, gap: md) {
component Button text: "Edit Profile" variant: primary
component Button text: "Change Password" variant: secondary
}
}
}
}
layout panel(padding: lg, background: "white") {
layout stack(direction: vertical, gap: md) {
component Heading text: "Contact Form"
component Input label: "Name" placeholder: "Full name"
component Input label: "Email" placeholder: "email@example.com"
component Textarea label: "Message" rows: 4 placeholder: "Your message..."
component Checkbox label: "Subscribe to newsletter"
layout stack(direction: horizontal, gap: md) {
component Button text: "Submit" variant: primary
component Button text: "Cancel" variant: secondary
}
}
}
layout grid(columns: 12, gap: md, padding: lg) {
cell span: 6 {
layout card(padding: md, gap: md, radius: lg, border: true) {
component Image type: square height: 200
component Heading text: "Premium Item"
component Text text: "High-quality product"
component Stat title: "Price" value: "$99.99"
component Button text: "Add to Cart" variant: primary
}
}
cell span: 6 {
layout card(padding: md, gap: md, radius: lg, border: true) {
component Image type: square height: 200
component Heading text: "Standard Item"
component Text text: "Good value option"
component Stat title: "Price" value: "$49.99"
component Button text: "Add to Cart" variant: primary
}
}
}
layout split(left: 280, gap: md) {
layout stack(direction: vertical, gap: md, padding: md) {
component Topbar title: "Admin Panel"
component SidebarMenu items: "Dashboard,Users,Reports,Settings" active: 0
component Divider
component Text text: "Settings"
component Link text: "Profile"
component Link text: "Logout"
}
layout stack(direction: vertical, gap: md, padding: lg) {
component Heading text: "Dashboard"
component Breadcrumbs items: "Home,Dashboard"
layout grid(columns: 12, gap: md) {
cell span: 12 {
layout card(padding: lg, gap: md) {
component Heading text: "Recent Activity"
component Table columns: "User,Action,Timestamp" rows: 5
}
}
}
}
}
Before generating output, verify:
- Syntax is valid Wire-DSL
- All components exist in the catalog
- Properties match component specifications
- No invalid property names
- Proper nesting of layouts
- At least one screen defined
- Style block is present
- No syntax errors (braces, quotes, colons)
- Component names match exactly (case-sensitive)
- All string values are quoted
- All layouts have explicit
paddingwhen needed - Image
typeuses valid values: "landscape", "square", "portrait" - Use
Imagefor profile pictures when needed - Grid cells have
spanvalues between 1-12 - Split fixed side width (
leftorright) is between 200-400 pixels - Card/Panel radius values are: "none", "sm", "md", "lg"
- Button variants are: "default", "primary", "secondary", "success", "warning", "danger", "info"
- Nested layouts are properly closed with braces
- Use sensible defaults (see section)
- Prefer common patterns (dashboard, form, card grid)
- When in doubt, choose
normaldensity andmdspacing - Use
stacklayout for linear content,gridfor multi-column - Default card/panel padding to
md, radius tomd
- Use most common variant:
primaryfor buttons,mdfor spacing - For numeric properties, use default spacing/padding
- For text, use descriptive placeholders
- For
Image type, use"square"as safe default - For lists/arrays, use comma-separated values in quotes
- Always include explicit
paddingfor readability - Default
gaptomdif spacing not specified - Default
columnsto12for grids - Default
directiontoverticalfor stacks - Default split fixed panel to
left: 260when no side is specified by the user
When the user asks for an interactive prototype or clickable wireframe, add event annotations. Events are metadata only — they do not affect static rendering but enable play test interactions.
Assign an id to components that will be shown/hidden/toggled by events:
layout modal(id: confirmModal, title: "Confirm deletion?") {
body { component Text text: "This cannot be undone." }
footer { component Button text: "Delete" variant: danger onClick: hide(confirmModal) }
}
component Button text: "Delete" onClick: show(confirmModal)
ID rules: [a-zA-Z_][a-zA-Z0-9_]* — no hyphens, cannot start with a digit.
// Button / IconButton / Link
component Button text: "Go" onClick: navigate(Dashboard)
component Button text: "Open" onClick: show(myPanel)
component Button text: "Close" onClick: hide(myPanel)
component Button text: "Toggle" onClick: toggle(sidePanel)
component Button text: "Tab 2" onClick: setTab(mainTabs, 1)
// Chained actions (& operator)
component Button text: "Delete" onClick: hide(listModal) & show(confirmModal)
component Button text: "Continue" onClick: hide(step1) & show(step2) & navigate(Summary)
// Toggle / Checkbox / Radio — use onChange OR onActive+onInactive (not both)
component Toggle label: "Show panel" onChange: toggle(advancedPanel)
component Checkbox label: "I agree"
onActive: show(submitBtn)
onInactive: hide(submitBtn)
// Table rows / List items
component Table columns: "Name,Role" rows: 8 onRowClick: navigate(UserDetail)
component List items: "A,B,C" onItemClick: navigate(ItemDetail)
// Modal (layout container — replaces component Modal)
layout modal(id: confirmModal, title: "Sure?", onClose: hide(self)) {
body { component Text text: "Confirm?" }
footer { component Button text: "Yes" onClick: hide(self) }
}
// SidebarMenu navigation
component SidebarMenu items: "Dashboard,Users,Settings"
onItemsClick: "DashboardScreen,UsersScreen,SettingsScreen"
Pair component Tabs with layout tabs using a shared id/tabsId:
component Tabs items: "Profile,Settings,Billing" initialActive: 0 tabsId: mainTabs
layout tabs(id: mainTabs) {
tab {
component Heading text: "Profile"
component Input label: "Full name"
}
tab {
component Heading text: "Settings"
component Toggle label: "Notifications"
}
tab {
component Heading text: "Billing"
component Table columns: "Date,Amount" rows: 4
}
}
layout card(padding: md, gap: md, onClick: navigate(UserDetail)) {
component Heading text: "User #1234"
component Text text: "Click to view profile"
}
Use layout modal (not component Modal) for overlay dialogs. Modal starts hidden, shown by a button:
layout modal(id: confirmModal, title: "Delete?", visible: false, closable: true) {
body {
component Text text: "This action cannot be undone."
}
footer {
component Button text: "Cancel" onClick: hide(self)
component Button text: "Delete" variant: danger onClick: hide(self)
}
}
component Button text: "Delete Item" variant: danger onClick: show(confirmModal)
Use self when a container/component closes itself — no explicit id needed on the action target:
layout modal(id: confirmModal, title: "Done?", onClose: hide(self)) {
footer { component Button text: "Close" onClick: hide(self) }
}
navigate(X)— X must be a declared screen nameshow/hide/toggle(X)— X must haveid: Xin the same screen (or useself)- Duplicate IDs in the same screen → error
onItemsClickscreen count must equalitemscountonChangeandonActive/onInactiveare mutually exclusive
Generated .wire files should pass:
wire validate <file.wire> # Syntax check
wire render <file.wire> --svg # Renders without errorsThis guide is designed to work alongside the DSL-SYNTAX.md document. For detailed component specifications, layout properties, and comprehensive examples, refer to the syntax guide.
padding render with 0px internal padding. Always specify padding: xs, padding: sm, padding: md, padding: lg, or padding: xl when spacing is needed inside containers.
When components require multiple items (like items, columns), use comma-separated strings:
component SidebarMenu items: "Home,Users,Settings" // ✅ Correct
component Table columns: "Name,Email,Status" // ✅ Correct
component Tabs items: "Profile,Settings,Activity" // ✅ Correct
LLM Prompt Guide v2.0
Compatible with: Wire-DSL v1.0+
Last Updated: January 2026
Status: Enhanced with advanced nesting examples and detailed property specifications
Remember: Clarity over brevity. Valid code over creative shortcuts.