This guide helps create distinctive, production-grade Canvas App screens that avoid generic "AI slop" aesthetics.
Who does what. Discovery tools (list_controls, describe_control, the data and API
tools) belong to the orchestrator and the canvas-app-planner. A canvas-screen-builder
cannot call them and works from the control definitions recorded in its screen brief.
Where this guide says "run list_controls", that instruction is addressed to the
orchestrator and planner.
- Design Thinking Process
- Control, Data Source, and API Discovery
- Typography and Color
- Spatial Composition and Layout
- Interactive States
- Visual Polish
- Aesthetic Anti-Patterns
- Creative Interpretation
- Design Process Summary
Before generating YAML, understand the context and commit to a BOLD aesthetic direction:
- Purpose: What problem does this screen solve? Who uses it? What's their context?
- Tone: Pick an extreme aesthetic direction - brutally minimal, maximalist information density, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, data-dense dashboard, etc.
- Differentiation: What makes this UNFORGETTABLE? What's the one thing someone will remember?
CRITICAL: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
Run list_controls before committing to any layout. The available controls are not just technical building blocks — they are design options. Designing without knowing what exists means you'll build inferior versions of things that already exist as polished, semantic components.
Key controls that directly expand your design vocabulary:
| Control | What it enables |
|---|---|
ModernCard |
Ready-made card with Title, Subtitle, Description hierarchy, built-in shadow, and OnSelect — use this as your card primitive, not GroupContainer. Set Image (or Image: =Blank()) and every text slot you display: unset slots render a stock photo and the literal words "Subtitle"/"Description". |
Avatar |
User/entity representation with image, initials fallback, and size variants — no need to fake it with a circle and a label |
Badge |
Status indicators, counts, and labels with semantic color variants — replaces ad-hoc colored rectangles with text |
Progress |
Linear and circular progress display — replaces manual progress bar constructions |
ModernTabList |
In-screen tab/panel navigation with selection state built in. Use ModernButtons for navigation between separate screens. |
The pattern to avoid: Choosing an aesthetic direction, then reaching for GroupContainer + Label + Rectangle to assemble something that already exists. The controls above are not conveniences — they are fundamentally better starting points with richer built-in behavior and visual consistency.
Run list_data_sources and list_apis before creating any local collections with ClearCollect() or Collect() calls. The
data sources and APIs you have access to are not just technical details — they are design constraints and opportunities.
Designing without knowing what data you can pull in and how means you'll create static, fake content that doesn't reflect
the real user experience.
- Control Selection: When there are multiple controls for the same purpose, and one of them is a "Classic" control, favor the modern controls:
- Favor
ModernTextoverLabel,ModernComboboxoverClassic/ComboBox,ModernRadiooverClassic/Radio,ButtonorModernButtonoverClassic/Button,ModernTabListfor in-screen tabs,ModernButtonrows for cross-screen navigation,ModernTextInputoverClassic/TextInput, and so on.
- Favor
- Font Weight: Use
ModernTextfor headlines withFontWeight: =FontWeight.Boldand a large font size. UseModernTextwithFontWeight: =FontWeight.Normalfor body content. - Size Contrast: Create dramatic hierarchy with size differences. Headers at 24-32, subheaders at 18-20, body at 14-16.
- Alignment as Statement: Mix
Align.Left,Align.Center,Align.Rightintentionally. Centered text for impact, left-aligned for readability. - Font Properties: Leverage
Size,FontWeight,Align,VerticalAlign, andColorto create visual interest. On the modern React controls the text color property isColorand the font size property isSize—FontColorandFontSizeexist only onBadge. Confirm withdescribe_controlrather than assuming.
- Commit to a Palette: Use
Colorconstants or customRGBA()values consistently throughout. - Dominant + Accent: Choose one dominant color for primary actions and backgrounds, with sharp contrasting accents. Avoid evenly distributed pastels.
- Contextual Color: Use
BasePaletteColoron buttons to reinforce hierarchy. - State-Based Color: Use formulas like
=If(isActive, Color.Blue, Color.Gray)to create dynamic interfaces. - Background Depth: Don't default to
Color.White. Use subtle grays, tinted backgrounds, or bold color fills.
- Layout Strategy Choice:
- Use
ManualLayoutfor precise, pixel-perfect designs - Use
AutoLayoutfor responsive, flexible layouts
- Use
- Design for the narrowest width you claim to support: A layout composed at 1440px and never re-checked will clip at 1024px and collapse on a phone. Size layout containers with
Parent.WidthorFillPortions, never a literal likeWidth: =1120. Reserve fixed pixel sizes for icons, avatars, and steppers — and keep interactive ones at 44px or larger. - Every horizontal row of more than two controls needs a reflow strategy: Set
LayoutWrap: =true, or driveLayoutDirectionfrom a width breakpoint, so rows stack instead of squeezing. This is the single most common defect in generated apps and it is invisible at the width you designed at. - The screen root must scroll whenever it holds a gallery, a form, or more than about three stacked sections: canvas screens do not scroll on their own, so give the root container
LayoutOverflowY: =LayoutOverflow.Scrolland content below the fold stays reachable on short viewports. - Set foreground wherever you set background: Text does not inherit a contrasting color. Every time you choose a container
Fill, setColoron the text inside it — dark-on-dark passes every automated check and is unreadable. - Rows inside a
Galleryneed their own container:Galleryis a Classic control and positions its template children absolutely, so a row authored at desktop width stays at desktop width everywhere. Put one AutoLayoutGroupContainerin the template and build the row inside it. See${PLUGIN_ROOT}/references/LayoutGuide.md. - Asymmetry & Breaking Grid: Don't center everything. Offset elements. Use unexpected positioning.
- Spacing as Design: Generous padding creates breathing room. Dense layouts create energy.
- Layering: Use multiple
GroupContainercontrols to create visual depth. - Scale Variation: Mix large and small controls. A massive header with tiny supporting text creates drama.
- Card UI — use
ModernCardas the starting point: For anything that functions as a card,ModernCardis the right primitive.GroupContainercannot be clicked and requires workarounds to match whatModernCardprovides natively — see${PLUGIN_ROOT}/references/ControlGuide.mdfor details.
- State-Driven Design: Use
Set()variables to create dynamic interfaces that respond to user actions. - DisplayMode as Design: Toggle between
DisplayMode.Edit,DisplayMode.View, andDisplayMode.Disabled. - Visibility Choreography: Use
Visibleproperty with state variables to reveal/hide elements. - Button States: Make buttons feel alive with
BasePaletteColorchanges based on state. - Conditional Styling: Every property can be a formula. Use
If()statements to changeFill,FontColor,Size.
- DropShadow: Use
DropShadow.Semilight,DropShadow.Regular,DropShadow.Heavyfor elevation and depth. Available onGroupContainerandModernCard. - Border Radius: Rounding is spelled differently per control.
GroupContainerand the modern text/input/button controls use the four corner propertiesRadiusTopLeft,RadiusTopRight,RadiusBottomLeft,RadiusBottomRight.ModernCarduses a single numericBorderRadius.Rectanglehas no rounding at all — use aGroupContainerwhen you need a rounded filled surface. Confirm withdescribe_controlbefore styling. - Transparency: Use RGBA with alpha < 1 for overlays, subtle backgrounds, and layering.
- Touch Targets: Make interactive elements at least 44px, preferably 48px, for mobile.
- Accessible by construction: Give every content and input control an
AccessibleLabel, and every interactive gallery aTabIndex, while you are designing it. Nothing downstream adds them for you, and retrofitting labels across a finished screen is far more work than writing them in place. - Data Visualization: Use appropriate controls with thoughtful
TemplateSizeand spacing.
Avoid these antipatterns:
Generic Color Choices:
- ❌ Default white backgrounds (
Color.White) with no variation - ❌ Overused blue accent colors without considering context
- ❌ Purple-on-white schemes that scream "generic business app"
- ❌ Timid pastels that lack visual impact
Predictable Layouts:
- ❌ Everything centered and evenly spaced with no hierarchy
- ❌ Uniform button sizes and spacing (everything at 40px height, 10px gaps)
- ❌ Forms that look like database entry screens
- ❌ Screens that are just vertical lists of identically-styled buttons
Lazy Control Choices:
- ❌ Using
Buttonfor everything when other controls are better - ❌ Defaulting to
Classiccontrols without considering alternatives - ❌ Not exploring specialized controls
- ❌ Generic control names like
Button1,Label2 - ❌ Building
Avatar,Badge,Progress,ModernTabList, or card layouts from primitives when the semantic controls exist — always run list_controls first
Timid Typography:
- ❌ All text at size 12-14 with no hierarchy
- ❌ Not using
FontWeight.BoldorFontWeight.Semiboldfor emphasis - ❌ Everything left-aligned or everything centered with no variation
- ❌ Ignoring the power of scale contrast
Missing Interactivity:
- ❌ Static screens with no state management or visual feedback
- ❌ Buttons that don't change appearance when clicked or disabled
- ❌ No use of
DisplayModeto guide user flows - ❌ Forgetting to use
Visibleproperty for progressive disclosure
No Attention to Detail:
- ❌ Ignoring spacing and letting everything be equidistant
- ❌ Not using
DropShadowor radius properties for visual depth - ❌ Forgetting to use
RGBA()for transparency effects - ❌ Uniform sizes across all controls
Interpret creatively and make unexpected choices:
- Vary Themes: Don't always use light backgrounds. Try dark themes, colored backgrounds, or bold fills.
- Mix Layout Strategies: Combine
ManualLayoutprecision withAutoLayoutflexibility. - Experiment with Control Types: Explore beyond basic buttons and labels.
- Context-Specific Palettes: A game uses playful colors. A dashboard uses data-viz colors. A form uses sophisticated grays.
- No Design Should Be the Same: Each screen should feel custom-designed for its purpose, not templated.
IMPORTANT: Match implementation complexity to the aesthetic vision:
- Maximalist designs need elaborate control hierarchies, dynamic state management, conditional visibility, layered containers, and rich color palettes.
- Minimalist designs need restraint, precision spacing, careful typography choices, subtle color usage, and attention to negative space.
- Elegance comes from executing the vision well, whether controlled chaos or refined simplicity.
- Discover your palette — Run list_controls before committing to any design direction
- Choose an aesthetic direction — Commit to a specific, bold tone (see Design Thinking Process above)
- Plan visual hierarchy — What are the primary, secondary, and tertiary elements? How do they relate?
- Choose layout strategy — ManualLayout for precision; AutoLayout for responsiveness
- Plan interactivity — What state variables drive dynamic behavior? What does the user experience over time?
- Implement YAML — Execute the vision with intentional aesthetic choices at every property
- Validate — Use compile_canvas early, not just at the end
- Refine — Polish spacing, color, sizing, and depth until the design feels intentional
Remember: Canvas Apps can be visually striking and memorable despite platform constraints. Don't hold back. Show what can truly be created when thinking outside the box and committing fully to a distinctive vision.